1 // Copyright 2012 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/heap.h" 6 7 #include "src/accessors.h" 8 #include "src/api.h" 9 #include "src/ast/scopeinfo.h" 10 #include "src/base/bits.h" 11 #include "src/base/once.h" 12 #include "src/base/utils/random-number-generator.h" 13 #include "src/bootstrapper.h" 14 #include "src/codegen.h" 15 #include "src/compilation-cache.h" 16 #include "src/conversions.h" 17 #include "src/debug/debug.h" 18 #include "src/deoptimizer.h" 19 #include "src/global-handles.h" 20 #include "src/heap/array-buffer-tracker.h" 21 #include "src/heap/gc-idle-time-handler.h" 22 #include "src/heap/gc-tracer.h" 23 #include "src/heap/incremental-marking.h" 24 #include "src/heap/mark-compact-inl.h" 25 #include "src/heap/mark-compact.h" 26 #include "src/heap/memory-reducer.h" 27 #include "src/heap/object-stats.h" 28 #include "src/heap/objects-visiting-inl.h" 29 #include "src/heap/objects-visiting.h" 30 #include "src/heap/scavenge-job.h" 31 #include "src/heap/scavenger-inl.h" 32 #include "src/heap/store-buffer.h" 33 #include "src/interpreter/interpreter.h" 34 #include "src/profiler/cpu-profiler.h" 35 #include "src/regexp/jsregexp.h" 36 #include "src/runtime-profiler.h" 37 #include "src/snapshot/natives.h" 38 #include "src/snapshot/serialize.h" 39 #include "src/snapshot/snapshot.h" 40 #include "src/type-feedback-vector.h" 41 #include "src/utils.h" 42 #include "src/v8.h" 43 #include "src/v8threads.h" 44 #include "src/vm-state-inl.h" 45 46 namespace v8 { 47 namespace internal { 48 49 50 struct Heap::StrongRootsList { 51 Object** start; 52 Object** end; 53 StrongRootsList* next; 54 }; 55 56 class IdleScavengeObserver : public InlineAllocationObserver { 57 public: 58 IdleScavengeObserver(Heap& heap, intptr_t step_size) 59 : InlineAllocationObserver(step_size), heap_(heap) {} 60 61 void Step(int bytes_allocated, Address, size_t) override { 62 heap_.ScheduleIdleScavengeIfNeeded(bytes_allocated); 63 } 64 65 private: 66 Heap& heap_; 67 }; 68 69 70 Heap::Heap() 71 : amount_of_external_allocated_memory_(0), 72 amount_of_external_allocated_memory_at_last_global_gc_(0), 73 isolate_(NULL), 74 code_range_size_(0), 75 // semispace_size_ should be a power of 2 and old_generation_size_ should 76 // be a multiple of Page::kPageSize. 77 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), 78 max_semi_space_size_(8 * (kPointerSize / 4) * MB), 79 initial_semispace_size_(Page::kPageSize), 80 target_semispace_size_(Page::kPageSize), 81 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), 82 initial_old_generation_size_(max_old_generation_size_ / 83 kInitalOldGenerationLimitFactor), 84 old_generation_size_configured_(false), 85 max_executable_size_(256ul * (kPointerSize / 4) * MB), 86 // Variables set based on semispace_size_ and old_generation_size_ in 87 // ConfigureHeap. 88 // Will be 4 * reserved_semispace_size_ to ensure that young 89 // generation can be aligned to its size. 90 maximum_committed_(0), 91 survived_since_last_expansion_(0), 92 survived_last_scavenge_(0), 93 always_allocate_scope_count_(0), 94 contexts_disposed_(0), 95 number_of_disposed_maps_(0), 96 global_ic_age_(0), 97 scan_on_scavenge_pages_(0), 98 new_space_(this), 99 old_space_(NULL), 100 code_space_(NULL), 101 map_space_(NULL), 102 lo_space_(NULL), 103 gc_state_(NOT_IN_GC), 104 gc_post_processing_depth_(0), 105 allocations_count_(0), 106 raw_allocations_hash_(0), 107 ms_count_(0), 108 gc_count_(0), 109 remembered_unmapped_pages_index_(0), 110 #ifdef DEBUG 111 allocation_timeout_(0), 112 #endif // DEBUG 113 old_generation_allocation_limit_(initial_old_generation_size_), 114 old_gen_exhausted_(false), 115 optimize_for_memory_usage_(false), 116 inline_allocation_disabled_(false), 117 store_buffer_rebuilder_(store_buffer()), 118 total_regexp_code_generated_(0), 119 tracer_(nullptr), 120 high_survival_rate_period_length_(0), 121 promoted_objects_size_(0), 122 promotion_ratio_(0), 123 semi_space_copied_object_size_(0), 124 previous_semi_space_copied_object_size_(0), 125 semi_space_copied_rate_(0), 126 nodes_died_in_new_space_(0), 127 nodes_copied_in_new_space_(0), 128 nodes_promoted_(0), 129 maximum_size_scavenges_(0), 130 max_gc_pause_(0.0), 131 total_gc_time_ms_(0.0), 132 max_alive_after_gc_(0), 133 min_in_mutator_(kMaxInt), 134 marking_time_(0.0), 135 sweeping_time_(0.0), 136 last_idle_notification_time_(0.0), 137 last_gc_time_(0.0), 138 scavenge_collector_(nullptr), 139 mark_compact_collector_(nullptr), 140 store_buffer_(this), 141 incremental_marking_(nullptr), 142 gc_idle_time_handler_(nullptr), 143 memory_reducer_(nullptr), 144 object_stats_(nullptr), 145 scavenge_job_(nullptr), 146 idle_scavenge_observer_(nullptr), 147 full_codegen_bytes_generated_(0), 148 crankshaft_codegen_bytes_generated_(0), 149 new_space_allocation_counter_(0), 150 old_generation_allocation_counter_(0), 151 old_generation_size_at_last_gc_(0), 152 gcs_since_last_deopt_(0), 153 global_pretenuring_feedback_(nullptr), 154 ring_buffer_full_(false), 155 ring_buffer_end_(0), 156 promotion_queue_(this), 157 configured_(false), 158 current_gc_flags_(Heap::kNoGCFlags), 159 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), 160 external_string_table_(this), 161 chunks_queued_for_free_(NULL), 162 concurrent_unmapping_tasks_active_(0), 163 pending_unmapping_tasks_semaphore_(0), 164 gc_callbacks_depth_(0), 165 deserialization_complete_(false), 166 strong_roots_list_(NULL), 167 array_buffer_tracker_(NULL), 168 heap_iterator_depth_(0), 169 force_oom_(false) { 170 // Allow build-time customization of the max semispace size. Building 171 // V8 with snapshots and a non-default max semispace size is much 172 // easier if you can define it as part of the build environment. 173 #if defined(V8_MAX_SEMISPACE_SIZE) 174 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; 175 #endif 176 177 // Ensure old_generation_size_ is a multiple of kPageSize. 178 DCHECK((max_old_generation_size_ & (Page::kPageSize - 1)) == 0); 179 180 memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); 181 set_native_contexts_list(NULL); 182 set_allocation_sites_list(Smi::FromInt(0)); 183 set_encountered_weak_collections(Smi::FromInt(0)); 184 set_encountered_weak_cells(Smi::FromInt(0)); 185 set_encountered_transition_arrays(Smi::FromInt(0)); 186 // Put a dummy entry in the remembered pages so we can find the list the 187 // minidump even if there are no real unmapped pages. 188 RememberUnmappedPage(NULL, false); 189 } 190 191 192 intptr_t Heap::Capacity() { 193 if (!HasBeenSetUp()) return 0; 194 195 return new_space_.Capacity() + old_space_->Capacity() + 196 code_space_->Capacity() + map_space_->Capacity(); 197 } 198 199 200 intptr_t Heap::CommittedOldGenerationMemory() { 201 if (!HasBeenSetUp()) return 0; 202 203 return old_space_->CommittedMemory() + code_space_->CommittedMemory() + 204 map_space_->CommittedMemory() + lo_space_->Size(); 205 } 206 207 208 intptr_t Heap::CommittedMemory() { 209 if (!HasBeenSetUp()) return 0; 210 211 return new_space_.CommittedMemory() + CommittedOldGenerationMemory(); 212 } 213 214 215 size_t Heap::CommittedPhysicalMemory() { 216 if (!HasBeenSetUp()) return 0; 217 218 return new_space_.CommittedPhysicalMemory() + 219 old_space_->CommittedPhysicalMemory() + 220 code_space_->CommittedPhysicalMemory() + 221 map_space_->CommittedPhysicalMemory() + 222 lo_space_->CommittedPhysicalMemory(); 223 } 224 225 226 intptr_t Heap::CommittedMemoryExecutable() { 227 if (!HasBeenSetUp()) return 0; 228 229 return isolate()->memory_allocator()->SizeExecutable(); 230 } 231 232 233 void Heap::UpdateMaximumCommitted() { 234 if (!HasBeenSetUp()) return; 235 236 intptr_t current_committed_memory = CommittedMemory(); 237 if (current_committed_memory > maximum_committed_) { 238 maximum_committed_ = current_committed_memory; 239 } 240 } 241 242 243 intptr_t Heap::Available() { 244 if (!HasBeenSetUp()) return 0; 245 246 intptr_t total = 0; 247 AllSpaces spaces(this); 248 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { 249 total += space->Available(); 250 } 251 return total; 252 } 253 254 255 bool Heap::HasBeenSetUp() { 256 return old_space_ != NULL && code_space_ != NULL && map_space_ != NULL && 257 lo_space_ != NULL; 258 } 259 260 261 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space, 262 const char** reason) { 263 // Is global GC requested? 264 if (space != NEW_SPACE) { 265 isolate_->counters()->gc_compactor_caused_by_request()->Increment(); 266 *reason = "GC in old space requested"; 267 return MARK_COMPACTOR; 268 } 269 270 if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) { 271 *reason = "GC in old space forced by flags"; 272 return MARK_COMPACTOR; 273 } 274 275 // Is enough data promoted to justify a global GC? 276 if (OldGenerationAllocationLimitReached()) { 277 isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment(); 278 *reason = "promotion limit reached"; 279 return MARK_COMPACTOR; 280 } 281 282 // Have allocation in OLD and LO failed? 283 if (old_gen_exhausted_) { 284 isolate_->counters() 285 ->gc_compactor_caused_by_oldspace_exhaustion() 286 ->Increment(); 287 *reason = "old generations exhausted"; 288 return MARK_COMPACTOR; 289 } 290 291 // Is there enough space left in OLD to guarantee that a scavenge can 292 // succeed? 293 // 294 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available 295 // for object promotion. It counts only the bytes that the memory 296 // allocator has not yet allocated from the OS and assigned to any space, 297 // and does not count available bytes already in the old space or code 298 // space. Undercounting is safe---we may get an unrequested full GC when 299 // a scavenge would have succeeded. 300 if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) { 301 isolate_->counters() 302 ->gc_compactor_caused_by_oldspace_exhaustion() 303 ->Increment(); 304 *reason = "scavenge might not succeed"; 305 return MARK_COMPACTOR; 306 } 307 308 // Default 309 *reason = NULL; 310 return SCAVENGER; 311 } 312 313 314 // TODO(1238405): Combine the infrastructure for --heap-stats and 315 // --log-gc to avoid the complicated preprocessor and flag testing. 316 void Heap::ReportStatisticsBeforeGC() { 317 // Heap::ReportHeapStatistics will also log NewSpace statistics when 318 // compiled --log-gc is set. The following logic is used to avoid 319 // double logging. 320 #ifdef DEBUG 321 if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics(); 322 if (FLAG_heap_stats) { 323 ReportHeapStatistics("Before GC"); 324 } else if (FLAG_log_gc) { 325 new_space_.ReportStatistics(); 326 } 327 if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms(); 328 #else 329 if (FLAG_log_gc) { 330 new_space_.CollectStatistics(); 331 new_space_.ReportStatistics(); 332 new_space_.ClearHistograms(); 333 } 334 #endif // DEBUG 335 } 336 337 338 void Heap::PrintShortHeapStatistics() { 339 if (!FLAG_trace_gc_verbose) return; 340 PrintIsolate(isolate_, "Memory allocator, used: %6" V8_PTR_PREFIX 341 "d KB" 342 ", available: %6" V8_PTR_PREFIX "d KB\n", 343 isolate_->memory_allocator()->Size() / KB, 344 isolate_->memory_allocator()->Available() / KB); 345 PrintIsolate(isolate_, "New space, used: %6" V8_PTR_PREFIX 346 "d KB" 347 ", available: %6" V8_PTR_PREFIX 348 "d KB" 349 ", committed: %6" V8_PTR_PREFIX "d KB\n", 350 new_space_.Size() / KB, new_space_.Available() / KB, 351 new_space_.CommittedMemory() / KB); 352 PrintIsolate(isolate_, "Old space, used: %6" V8_PTR_PREFIX 353 "d KB" 354 ", available: %6" V8_PTR_PREFIX 355 "d KB" 356 ", committed: %6" V8_PTR_PREFIX "d KB\n", 357 old_space_->SizeOfObjects() / KB, old_space_->Available() / KB, 358 old_space_->CommittedMemory() / KB); 359 PrintIsolate(isolate_, "Code space, used: %6" V8_PTR_PREFIX 360 "d KB" 361 ", available: %6" V8_PTR_PREFIX 362 "d KB" 363 ", committed: %6" V8_PTR_PREFIX "d KB\n", 364 code_space_->SizeOfObjects() / KB, code_space_->Available() / KB, 365 code_space_->CommittedMemory() / KB); 366 PrintIsolate(isolate_, "Map space, used: %6" V8_PTR_PREFIX 367 "d KB" 368 ", available: %6" V8_PTR_PREFIX 369 "d KB" 370 ", committed: %6" V8_PTR_PREFIX "d KB\n", 371 map_space_->SizeOfObjects() / KB, map_space_->Available() / KB, 372 map_space_->CommittedMemory() / KB); 373 PrintIsolate(isolate_, "Large object space, used: %6" V8_PTR_PREFIX 374 "d KB" 375 ", available: %6" V8_PTR_PREFIX 376 "d KB" 377 ", committed: %6" V8_PTR_PREFIX "d KB\n", 378 lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB, 379 lo_space_->CommittedMemory() / KB); 380 PrintIsolate(isolate_, "All spaces, used: %6" V8_PTR_PREFIX 381 "d KB" 382 ", available: %6" V8_PTR_PREFIX 383 "d KB" 384 ", committed: %6" V8_PTR_PREFIX "d KB\n", 385 this->SizeOfObjects() / KB, this->Available() / KB, 386 this->CommittedMemory() / KB); 387 PrintIsolate( 388 isolate_, "External memory reported: %6" V8_PTR_PREFIX "d KB\n", 389 static_cast<intptr_t>(amount_of_external_allocated_memory_ / KB)); 390 PrintIsolate(isolate_, "Total time spent in GC : %.1f ms\n", 391 total_gc_time_ms_); 392 } 393 394 395 // TODO(1238405): Combine the infrastructure for --heap-stats and 396 // --log-gc to avoid the complicated preprocessor and flag testing. 397 void Heap::ReportStatisticsAfterGC() { 398 // Similar to the before GC, we use some complicated logic to ensure that 399 // NewSpace statistics are logged exactly once when --log-gc is turned on. 400 #if defined(DEBUG) 401 if (FLAG_heap_stats) { 402 new_space_.CollectStatistics(); 403 ReportHeapStatistics("After GC"); 404 } else if (FLAG_log_gc) { 405 new_space_.ReportStatistics(); 406 } 407 #else 408 if (FLAG_log_gc) new_space_.ReportStatistics(); 409 #endif // DEBUG 410 for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount); 411 ++i) { 412 int count = deferred_counters_[i]; 413 deferred_counters_[i] = 0; 414 while (count > 0) { 415 count--; 416 isolate()->CountUsage(static_cast<v8::Isolate::UseCounterFeature>(i)); 417 } 418 } 419 } 420 421 422 void Heap::IncrementDeferredCount(v8::Isolate::UseCounterFeature feature) { 423 deferred_counters_[feature]++; 424 } 425 426 427 void Heap::GarbageCollectionPrologue() { 428 { 429 AllowHeapAllocation for_the_first_part_of_prologue; 430 gc_count_++; 431 432 #ifdef VERIFY_HEAP 433 if (FLAG_verify_heap) { 434 Verify(); 435 } 436 #endif 437 } 438 439 // Reset GC statistics. 440 promoted_objects_size_ = 0; 441 previous_semi_space_copied_object_size_ = semi_space_copied_object_size_; 442 semi_space_copied_object_size_ = 0; 443 nodes_died_in_new_space_ = 0; 444 nodes_copied_in_new_space_ = 0; 445 nodes_promoted_ = 0; 446 447 UpdateMaximumCommitted(); 448 449 #ifdef DEBUG 450 DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); 451 452 if (FLAG_gc_verbose) Print(); 453 454 ReportStatisticsBeforeGC(); 455 #endif // DEBUG 456 457 store_buffer()->GCPrologue(); 458 459 if (isolate()->concurrent_osr_enabled()) { 460 isolate()->optimizing_compile_dispatcher()->AgeBufferedOsrJobs(); 461 } 462 463 if (new_space_.IsAtMaximumCapacity()) { 464 maximum_size_scavenges_++; 465 } else { 466 maximum_size_scavenges_ = 0; 467 } 468 CheckNewSpaceExpansionCriteria(); 469 UpdateNewSpaceAllocationCounter(); 470 } 471 472 473 intptr_t Heap::SizeOfObjects() { 474 intptr_t total = 0; 475 AllSpaces spaces(this); 476 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { 477 total += space->SizeOfObjects(); 478 } 479 return total; 480 } 481 482 483 const char* Heap::GetSpaceName(int idx) { 484 switch (idx) { 485 case NEW_SPACE: 486 return "new_space"; 487 case OLD_SPACE: 488 return "old_space"; 489 case MAP_SPACE: 490 return "map_space"; 491 case CODE_SPACE: 492 return "code_space"; 493 case LO_SPACE: 494 return "large_object_space"; 495 default: 496 UNREACHABLE(); 497 } 498 return nullptr; 499 } 500 501 502 void Heap::RepairFreeListsAfterDeserialization() { 503 PagedSpaces spaces(this); 504 for (PagedSpace* space = spaces.next(); space != NULL; 505 space = spaces.next()) { 506 space->RepairFreeListsAfterDeserialization(); 507 } 508 } 509 510 511 void Heap::MergeAllocationSitePretenuringFeedback( 512 const HashMap& local_pretenuring_feedback) { 513 AllocationSite* site = nullptr; 514 for (HashMap::Entry* local_entry = local_pretenuring_feedback.Start(); 515 local_entry != nullptr; 516 local_entry = local_pretenuring_feedback.Next(local_entry)) { 517 site = reinterpret_cast<AllocationSite*>(local_entry->key); 518 MapWord map_word = site->map_word(); 519 if (map_word.IsForwardingAddress()) { 520 site = AllocationSite::cast(map_word.ToForwardingAddress()); 521 } 522 DCHECK(site->IsAllocationSite()); 523 int value = 524 static_cast<int>(reinterpret_cast<intptr_t>(local_entry->value)); 525 DCHECK_GT(value, 0); 526 527 { 528 // TODO(mlippautz): For parallel processing we need synchronization here. 529 if (site->IncrementMementoFoundCount(value)) { 530 global_pretenuring_feedback_->LookupOrInsert( 531 site, static_cast<uint32_t>(bit_cast<uintptr_t>(site))); 532 } 533 } 534 } 535 } 536 537 538 class Heap::PretenuringScope { 539 public: 540 explicit PretenuringScope(Heap* heap) : heap_(heap) { 541 heap_->global_pretenuring_feedback_ = 542 new HashMap(HashMap::PointersMatch, kInitialFeedbackCapacity); 543 } 544 545 ~PretenuringScope() { 546 delete heap_->global_pretenuring_feedback_; 547 heap_->global_pretenuring_feedback_ = nullptr; 548 } 549 550 private: 551 Heap* heap_; 552 }; 553 554 555 void Heap::ProcessPretenuringFeedback() { 556 bool trigger_deoptimization = false; 557 if (FLAG_allocation_site_pretenuring) { 558 int tenure_decisions = 0; 559 int dont_tenure_decisions = 0; 560 int allocation_mementos_found = 0; 561 int allocation_sites = 0; 562 int active_allocation_sites = 0; 563 564 AllocationSite* site = nullptr; 565 566 // Step 1: Digest feedback for recorded allocation sites. 567 bool maximum_size_scavenge = MaximumSizeScavenge(); 568 for (HashMap::Entry* e = global_pretenuring_feedback_->Start(); 569 e != nullptr; e = global_pretenuring_feedback_->Next(e)) { 570 site = reinterpret_cast<AllocationSite*>(e->key); 571 int found_count = site->memento_found_count(); 572 // The fact that we have an entry in the storage means that we've found 573 // the site at least once. 574 DCHECK_GT(found_count, 0); 575 DCHECK(site->IsAllocationSite()); 576 allocation_sites++; 577 active_allocation_sites++; 578 allocation_mementos_found += found_count; 579 if (site->DigestPretenuringFeedback(maximum_size_scavenge)) { 580 trigger_deoptimization = true; 581 } 582 if (site->GetPretenureMode() == TENURED) { 583 tenure_decisions++; 584 } else { 585 dont_tenure_decisions++; 586 } 587 } 588 589 // Step 2: Deopt maybe tenured allocation sites if necessary. 590 bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites(); 591 if (deopt_maybe_tenured) { 592 Object* list_element = allocation_sites_list(); 593 while (list_element->IsAllocationSite()) { 594 site = AllocationSite::cast(list_element); 595 DCHECK(site->IsAllocationSite()); 596 allocation_sites++; 597 if (site->IsMaybeTenure()) { 598 site->set_deopt_dependent_code(true); 599 trigger_deoptimization = true; 600 } 601 list_element = site->weak_next(); 602 } 603 } 604 605 if (trigger_deoptimization) { 606 isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); 607 } 608 609 if (FLAG_trace_pretenuring_statistics && 610 (allocation_mementos_found > 0 || tenure_decisions > 0 || 611 dont_tenure_decisions > 0)) { 612 PrintIsolate(isolate(), 613 "pretenuring: deopt_maybe_tenured=%d visited_sites=%d " 614 "active_sites=%d " 615 "mementos=%d tenured=%d not_tenured=%d\n", 616 deopt_maybe_tenured ? 1 : 0, allocation_sites, 617 active_allocation_sites, allocation_mementos_found, 618 tenure_decisions, dont_tenure_decisions); 619 } 620 } 621 } 622 623 624 void Heap::DeoptMarkedAllocationSites() { 625 // TODO(hpayer): If iterating over the allocation sites list becomes a 626 // performance issue, use a cache data structure in heap instead. 627 Object* list_element = allocation_sites_list(); 628 while (list_element->IsAllocationSite()) { 629 AllocationSite* site = AllocationSite::cast(list_element); 630 if (site->deopt_dependent_code()) { 631 site->dependent_code()->MarkCodeForDeoptimization( 632 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); 633 site->set_deopt_dependent_code(false); 634 } 635 list_element = site->weak_next(); 636 } 637 Deoptimizer::DeoptimizeMarkedCode(isolate_); 638 } 639 640 641 void Heap::GarbageCollectionEpilogue() { 642 store_buffer()->GCEpilogue(); 643 644 // In release mode, we only zap the from space under heap verification. 645 if (Heap::ShouldZapGarbage()) { 646 ZapFromSpace(); 647 } 648 649 #ifdef VERIFY_HEAP 650 if (FLAG_verify_heap) { 651 Verify(); 652 } 653 #endif 654 655 AllowHeapAllocation for_the_rest_of_the_epilogue; 656 657 #ifdef DEBUG 658 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); 659 if (FLAG_print_handles) PrintHandles(); 660 if (FLAG_gc_verbose) Print(); 661 if (FLAG_code_stats) ReportCodeStatistics("After GC"); 662 if (FLAG_check_handle_count) CheckHandleCount(); 663 #endif 664 if (FLAG_deopt_every_n_garbage_collections > 0) { 665 // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that 666 // the topmost optimized frame can be deoptimized safely, because it 667 // might not have a lazy bailout point right after its current PC. 668 if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) { 669 Deoptimizer::DeoptimizeAll(isolate()); 670 gcs_since_last_deopt_ = 0; 671 } 672 } 673 674 UpdateMaximumCommitted(); 675 676 isolate_->counters()->alive_after_last_gc()->Set( 677 static_cast<int>(SizeOfObjects())); 678 679 isolate_->counters()->string_table_capacity()->Set( 680 string_table()->Capacity()); 681 isolate_->counters()->number_of_symbols()->Set( 682 string_table()->NumberOfElements()); 683 684 if (full_codegen_bytes_generated_ + crankshaft_codegen_bytes_generated_ > 0) { 685 isolate_->counters()->codegen_fraction_crankshaft()->AddSample( 686 static_cast<int>((crankshaft_codegen_bytes_generated_ * 100.0) / 687 (crankshaft_codegen_bytes_generated_ + 688 full_codegen_bytes_generated_))); 689 } 690 691 if (CommittedMemory() > 0) { 692 isolate_->counters()->external_fragmentation_total()->AddSample( 693 static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory())); 694 695 isolate_->counters()->heap_fraction_new_space()->AddSample(static_cast<int>( 696 (new_space()->CommittedMemory() * 100.0) / CommittedMemory())); 697 isolate_->counters()->heap_fraction_old_space()->AddSample(static_cast<int>( 698 (old_space()->CommittedMemory() * 100.0) / CommittedMemory())); 699 isolate_->counters()->heap_fraction_code_space()->AddSample( 700 static_cast<int>((code_space()->CommittedMemory() * 100.0) / 701 CommittedMemory())); 702 isolate_->counters()->heap_fraction_map_space()->AddSample(static_cast<int>( 703 (map_space()->CommittedMemory() * 100.0) / CommittedMemory())); 704 isolate_->counters()->heap_fraction_lo_space()->AddSample(static_cast<int>( 705 (lo_space()->CommittedMemory() * 100.0) / CommittedMemory())); 706 707 isolate_->counters()->heap_sample_total_committed()->AddSample( 708 static_cast<int>(CommittedMemory() / KB)); 709 isolate_->counters()->heap_sample_total_used()->AddSample( 710 static_cast<int>(SizeOfObjects() / KB)); 711 isolate_->counters()->heap_sample_map_space_committed()->AddSample( 712 static_cast<int>(map_space()->CommittedMemory() / KB)); 713 isolate_->counters()->heap_sample_code_space_committed()->AddSample( 714 static_cast<int>(code_space()->CommittedMemory() / KB)); 715 716 isolate_->counters()->heap_sample_maximum_committed()->AddSample( 717 static_cast<int>(MaximumCommittedMemory() / KB)); 718 } 719 720 #define UPDATE_COUNTERS_FOR_SPACE(space) \ 721 isolate_->counters()->space##_bytes_available()->Set( \ 722 static_cast<int>(space()->Available())); \ 723 isolate_->counters()->space##_bytes_committed()->Set( \ 724 static_cast<int>(space()->CommittedMemory())); \ 725 isolate_->counters()->space##_bytes_used()->Set( \ 726 static_cast<int>(space()->SizeOfObjects())); 727 #define UPDATE_FRAGMENTATION_FOR_SPACE(space) \ 728 if (space()->CommittedMemory() > 0) { \ 729 isolate_->counters()->external_fragmentation_##space()->AddSample( \ 730 static_cast<int>(100 - \ 731 (space()->SizeOfObjects() * 100.0) / \ 732 space()->CommittedMemory())); \ 733 } 734 #define UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(space) \ 735 UPDATE_COUNTERS_FOR_SPACE(space) \ 736 UPDATE_FRAGMENTATION_FOR_SPACE(space) 737 738 UPDATE_COUNTERS_FOR_SPACE(new_space) 739 UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_space) 740 UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space) 741 UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space) 742 UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space) 743 #undef UPDATE_COUNTERS_FOR_SPACE 744 #undef UPDATE_FRAGMENTATION_FOR_SPACE 745 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE 746 747 #ifdef DEBUG 748 ReportStatisticsAfterGC(); 749 #endif // DEBUG 750 751 // Remember the last top pointer so that we can later find out 752 // whether we allocated in new space since the last GC. 753 new_space_top_after_last_gc_ = new_space()->top(); 754 last_gc_time_ = MonotonicallyIncreasingTimeInMs(); 755 756 ReduceNewSpaceSize(); 757 } 758 759 760 void Heap::PreprocessStackTraces() { 761 WeakFixedArray::Iterator iterator(weak_stack_trace_list()); 762 FixedArray* elements; 763 while ((elements = iterator.Next<FixedArray>())) { 764 for (int j = 1; j < elements->length(); j += 4) { 765 Object* maybe_code = elements->get(j + 2); 766 // If GC happens while adding a stack trace to the weak fixed array, 767 // which has been copied into a larger backing store, we may run into 768 // a stack trace that has already been preprocessed. Guard against this. 769 if (!maybe_code->IsCode()) break; 770 Code* code = Code::cast(maybe_code); 771 int offset = Smi::cast(elements->get(j + 3))->value(); 772 Address pc = code->address() + offset; 773 int pos = code->SourcePosition(pc); 774 elements->set(j + 2, Smi::FromInt(pos)); 775 } 776 } 777 // We must not compact the weak fixed list here, as we may be in the middle 778 // of writing to it, when the GC triggered. Instead, we reset the root value. 779 set_weak_stack_trace_list(Smi::FromInt(0)); 780 } 781 782 783 class GCCallbacksScope { 784 public: 785 explicit GCCallbacksScope(Heap* heap) : heap_(heap) { 786 heap_->gc_callbacks_depth_++; 787 } 788 ~GCCallbacksScope() { heap_->gc_callbacks_depth_--; } 789 790 bool CheckReenter() { return heap_->gc_callbacks_depth_ == 1; } 791 792 private: 793 Heap* heap_; 794 }; 795 796 797 void Heap::HandleGCRequest() { 798 if (incremental_marking()->request_type() == 799 IncrementalMarking::COMPLETE_MARKING) { 800 CollectAllGarbage(current_gc_flags_, "GC interrupt", 801 current_gc_callback_flags_); 802 } else if (incremental_marking()->IsMarking() && 803 !incremental_marking()->finalize_marking_completed()) { 804 FinalizeIncrementalMarking("GC interrupt: finalize incremental marking"); 805 } 806 } 807 808 809 void Heap::ScheduleIdleScavengeIfNeeded(int bytes_allocated) { 810 scavenge_job_->ScheduleIdleTaskIfNeeded(this, bytes_allocated); 811 } 812 813 814 void Heap::FinalizeIncrementalMarking(const char* gc_reason) { 815 if (FLAG_trace_incremental_marking) { 816 PrintF("[IncrementalMarking] (%s).\n", gc_reason); 817 } 818 819 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE); 820 HistogramTimerScope incremental_marking_scope( 821 isolate()->counters()->gc_incremental_marking_finalize()); 822 823 { 824 GCCallbacksScope scope(this); 825 if (scope.CheckReenter()) { 826 AllowHeapAllocation allow_allocation; 827 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); 828 VMState<EXTERNAL> state(isolate_); 829 HandleScope handle_scope(isolate_); 830 CallGCPrologueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags); 831 } 832 } 833 incremental_marking()->FinalizeIncrementally(); 834 { 835 GCCallbacksScope scope(this); 836 if (scope.CheckReenter()) { 837 AllowHeapAllocation allow_allocation; 838 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); 839 VMState<EXTERNAL> state(isolate_); 840 HandleScope handle_scope(isolate_); 841 CallGCEpilogueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags); 842 } 843 } 844 } 845 846 847 HistogramTimer* Heap::GCTypeTimer(GarbageCollector collector) { 848 if (collector == SCAVENGER) { 849 return isolate_->counters()->gc_scavenger(); 850 } else { 851 if (!incremental_marking()->IsStopped()) { 852 if (ShouldReduceMemory()) { 853 return isolate_->counters()->gc_finalize_reduce_memory(); 854 } else { 855 return isolate_->counters()->gc_finalize(); 856 } 857 } else { 858 return isolate_->counters()->gc_compactor(); 859 } 860 } 861 } 862 863 864 void Heap::CollectAllGarbage(int flags, const char* gc_reason, 865 const v8::GCCallbackFlags gc_callback_flags) { 866 // Since we are ignoring the return value, the exact choice of space does 867 // not matter, so long as we do not specify NEW_SPACE, which would not 868 // cause a full GC. 869 set_current_gc_flags(flags); 870 CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags); 871 set_current_gc_flags(kNoGCFlags); 872 } 873 874 875 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { 876 // Since we are ignoring the return value, the exact choice of space does 877 // not matter, so long as we do not specify NEW_SPACE, which would not 878 // cause a full GC. 879 // Major GC would invoke weak handle callbacks on weakly reachable 880 // handles, but won't collect weakly reachable objects until next 881 // major GC. Therefore if we collect aggressively and weak handle callback 882 // has been invoked, we rerun major GC to release objects which become 883 // garbage. 884 // Note: as weak callbacks can execute arbitrary code, we cannot 885 // hope that eventually there will be no weak callbacks invocations. 886 // Therefore stop recollecting after several attempts. 887 if (isolate()->concurrent_recompilation_enabled()) { 888 // The optimizing compiler may be unnecessarily holding on to memory. 889 DisallowHeapAllocation no_recursive_gc; 890 isolate()->optimizing_compile_dispatcher()->Flush(); 891 } 892 isolate()->ClearSerializerData(); 893 set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask); 894 isolate_->compilation_cache()->Clear(); 895 const int kMaxNumberOfAttempts = 7; 896 const int kMinNumberOfAttempts = 2; 897 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { 898 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, 899 v8::kGCCallbackFlagForced) && 900 attempt + 1 >= kMinNumberOfAttempts) { 901 break; 902 } 903 } 904 set_current_gc_flags(kNoGCFlags); 905 new_space_.Shrink(); 906 UncommitFromSpace(); 907 } 908 909 910 void Heap::ReportExternalMemoryPressure(const char* gc_reason) { 911 if (incremental_marking()->IsStopped()) { 912 if (incremental_marking()->CanBeActivated()) { 913 StartIncrementalMarking( 914 i::Heap::kNoGCFlags, 915 kGCCallbackFlagSynchronousPhantomCallbackProcessing, gc_reason); 916 } else { 917 CollectAllGarbage(i::Heap::kNoGCFlags, gc_reason, 918 kGCCallbackFlagSynchronousPhantomCallbackProcessing); 919 } 920 } else { 921 // Incremental marking is turned on an has already been started. 922 923 // TODO(mlippautz): Compute the time slice for incremental marking based on 924 // memory pressure. 925 double deadline = MonotonicallyIncreasingTimeInMs() + 926 FLAG_external_allocation_limit_incremental_time; 927 incremental_marking()->AdvanceIncrementalMarking( 928 0, deadline, 929 IncrementalMarking::StepActions(IncrementalMarking::GC_VIA_STACK_GUARD, 930 IncrementalMarking::FORCE_MARKING, 931 IncrementalMarking::FORCE_COMPLETION)); 932 } 933 } 934 935 936 void Heap::EnsureFillerObjectAtTop() { 937 // There may be an allocation memento behind every object in new space. 938 // If we evacuate a not full new space or if we are on the last page of 939 // the new space, then there may be uninitialized memory behind the top 940 // pointer of the new space page. We store a filler object there to 941 // identify the unused space. 942 Address from_top = new_space_.top(); 943 // Check that from_top is inside its page (i.e., not at the end). 944 Address space_end = new_space_.ToSpaceEnd(); 945 if (from_top < space_end) { 946 Page* page = Page::FromAddress(from_top); 947 if (page->Contains(from_top)) { 948 int remaining_in_page = static_cast<int>(page->area_end() - from_top); 949 CreateFillerObjectAt(from_top, remaining_in_page); 950 } 951 } 952 } 953 954 955 bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, 956 const char* collector_reason, 957 const v8::GCCallbackFlags gc_callback_flags) { 958 // The VM is in the GC state until exiting this function. 959 VMState<GC> state(isolate_); 960 961 #ifdef DEBUG 962 // Reset the allocation timeout to the GC interval, but make sure to 963 // allow at least a few allocations after a collection. The reason 964 // for this is that we have a lot of allocation sequences and we 965 // assume that a garbage collection will allow the subsequent 966 // allocation attempts to go through. 967 allocation_timeout_ = Max(6, FLAG_gc_interval); 968 #endif 969 970 EnsureFillerObjectAtTop(); 971 972 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { 973 if (FLAG_trace_incremental_marking) { 974 PrintF("[IncrementalMarking] Scavenge during marking.\n"); 975 } 976 } 977 978 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && 979 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && 980 !incremental_marking()->should_hurry() && FLAG_incremental_marking && 981 OldGenerationAllocationLimitReached()) { 982 // Make progress in incremental marking. 983 const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB; 984 incremental_marking()->Step(kStepSizeWhenDelayedByScavenge, 985 IncrementalMarking::NO_GC_VIA_STACK_GUARD); 986 if (!incremental_marking()->IsComplete() && 987 !mark_compact_collector()->marking_deque_.IsEmpty() && 988 !FLAG_gc_global) { 989 if (FLAG_trace_incremental_marking) { 990 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); 991 } 992 collector = SCAVENGER; 993 collector_reason = "incremental marking delaying mark-sweep"; 994 } 995 } 996 997 bool next_gc_likely_to_collect_more = false; 998 intptr_t committed_memory_before = 0; 999 1000 if (collector == MARK_COMPACTOR) { 1001 committed_memory_before = CommittedOldGenerationMemory(); 1002 } 1003 1004 { 1005 tracer()->Start(collector, gc_reason, collector_reason); 1006 DCHECK(AllowHeapAllocation::IsAllowed()); 1007 DisallowHeapAllocation no_allocation_during_gc; 1008 GarbageCollectionPrologue(); 1009 1010 { 1011 HistogramTimerScope histogram_timer_scope(GCTypeTimer(collector)); 1012 1013 next_gc_likely_to_collect_more = 1014 PerformGarbageCollection(collector, gc_callback_flags); 1015 } 1016 1017 GarbageCollectionEpilogue(); 1018 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { 1019 isolate()->CheckDetachedContextsAfterGC(); 1020 } 1021 1022 if (collector == MARK_COMPACTOR) { 1023 intptr_t committed_memory_after = CommittedOldGenerationMemory(); 1024 intptr_t used_memory_after = PromotedSpaceSizeOfObjects(); 1025 MemoryReducer::Event event; 1026 event.type = MemoryReducer::kMarkCompact; 1027 event.time_ms = MonotonicallyIncreasingTimeInMs(); 1028 // Trigger one more GC if 1029 // - this GC decreased committed memory, 1030 // - there is high fragmentation, 1031 // - there are live detached contexts. 1032 event.next_gc_likely_to_collect_more = 1033 (committed_memory_before - committed_memory_after) > MB || 1034 HasHighFragmentation(used_memory_after, committed_memory_after) || 1035 (detached_contexts()->length() > 0); 1036 if (deserialization_complete_) { 1037 memory_reducer_->NotifyMarkCompact(event); 1038 } 1039 } 1040 1041 tracer()->Stop(collector); 1042 } 1043 1044 if (collector == MARK_COMPACTOR && 1045 (gc_callback_flags & kGCCallbackFlagForced) != 0) { 1046 isolate()->CountUsage(v8::Isolate::kForcedGC); 1047 } 1048 1049 // Start incremental marking for the next cycle. The heap snapshot 1050 // generator needs incremental marking to stay off after it aborted. 1051 if (!ShouldAbortIncrementalMarking() && incremental_marking()->IsStopped() && 1052 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { 1053 StartIncrementalMarking(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); 1054 } 1055 1056 return next_gc_likely_to_collect_more; 1057 } 1058 1059 1060 int Heap::NotifyContextDisposed(bool dependant_context) { 1061 if (!dependant_context) { 1062 tracer()->ResetSurvivalEvents(); 1063 old_generation_size_configured_ = false; 1064 MemoryReducer::Event event; 1065 event.type = MemoryReducer::kContextDisposed; 1066 event.time_ms = MonotonicallyIncreasingTimeInMs(); 1067 memory_reducer_->NotifyContextDisposed(event); 1068 } 1069 if (isolate()->concurrent_recompilation_enabled()) { 1070 // Flush the queued recompilation tasks. 1071 isolate()->optimizing_compile_dispatcher()->Flush(); 1072 } 1073 AgeInlineCaches(); 1074 number_of_disposed_maps_ = retained_maps()->Length(); 1075 tracer()->AddContextDisposalTime(MonotonicallyIncreasingTimeInMs()); 1076 return ++contexts_disposed_; 1077 } 1078 1079 1080 void Heap::StartIncrementalMarking(int gc_flags, 1081 const GCCallbackFlags gc_callback_flags, 1082 const char* reason) { 1083 DCHECK(incremental_marking()->IsStopped()); 1084 set_current_gc_flags(gc_flags); 1085 current_gc_callback_flags_ = gc_callback_flags; 1086 incremental_marking()->Start(reason); 1087 } 1088 1089 1090 void Heap::StartIdleIncrementalMarking() { 1091 gc_idle_time_handler_->ResetNoProgressCounter(); 1092 StartIncrementalMarking(kReduceMemoryFootprintMask, kNoGCCallbackFlags, 1093 "idle"); 1094 } 1095 1096 1097 void Heap::MoveElements(FixedArray* array, int dst_index, int src_index, 1098 int len) { 1099 if (len == 0) return; 1100 1101 DCHECK(array->map() != fixed_cow_array_map()); 1102 Object** dst_objects = array->data_start() + dst_index; 1103 MemMove(dst_objects, array->data_start() + src_index, len * kPointerSize); 1104 if (!InNewSpace(array)) { 1105 for (int i = 0; i < len; i++) { 1106 // TODO(hpayer): check store buffer for entries 1107 if (InNewSpace(dst_objects[i])) { 1108 RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i)); 1109 } 1110 } 1111 } 1112 incremental_marking()->RecordWrites(array); 1113 } 1114 1115 1116 #ifdef VERIFY_HEAP 1117 // Helper class for verifying the string table. 1118 class StringTableVerifier : public ObjectVisitor { 1119 public: 1120 void VisitPointers(Object** start, Object** end) override { 1121 // Visit all HeapObject pointers in [start, end). 1122 for (Object** p = start; p < end; p++) { 1123 if ((*p)->IsHeapObject()) { 1124 // Check that the string is actually internalized. 1125 CHECK((*p)->IsTheHole() || (*p)->IsUndefined() || 1126 (*p)->IsInternalizedString()); 1127 } 1128 } 1129 } 1130 }; 1131 1132 1133 static void VerifyStringTable(Heap* heap) { 1134 StringTableVerifier verifier; 1135 heap->string_table()->IterateElements(&verifier); 1136 } 1137 #endif // VERIFY_HEAP 1138 1139 1140 bool Heap::ReserveSpace(Reservation* reservations) { 1141 bool gc_performed = true; 1142 int counter = 0; 1143 static const int kThreshold = 20; 1144 while (gc_performed && counter++ < kThreshold) { 1145 gc_performed = false; 1146 for (int space = NEW_SPACE; space < Serializer::kNumberOfSpaces; space++) { 1147 Reservation* reservation = &reservations[space]; 1148 DCHECK_LE(1, reservation->length()); 1149 if (reservation->at(0).size == 0) continue; 1150 bool perform_gc = false; 1151 if (space == LO_SPACE) { 1152 DCHECK_EQ(1, reservation->length()); 1153 perform_gc = !CanExpandOldGeneration(reservation->at(0).size); 1154 } else { 1155 for (auto& chunk : *reservation) { 1156 AllocationResult allocation; 1157 int size = chunk.size; 1158 DCHECK_LE(size, MemoryAllocator::PageAreaSize( 1159 static_cast<AllocationSpace>(space))); 1160 if (space == NEW_SPACE) { 1161 allocation = new_space()->AllocateRawUnaligned(size); 1162 } else { 1163 allocation = paged_space(space)->AllocateRawUnaligned(size); 1164 } 1165 HeapObject* free_space = nullptr; 1166 if (allocation.To(&free_space)) { 1167 // Mark with a free list node, in case we have a GC before 1168 // deserializing. 1169 Address free_space_address = free_space->address(); 1170 CreateFillerObjectAt(free_space_address, size); 1171 DCHECK(space < Serializer::kNumberOfPreallocatedSpaces); 1172 chunk.start = free_space_address; 1173 chunk.end = free_space_address + size; 1174 } else { 1175 perform_gc = true; 1176 break; 1177 } 1178 } 1179 } 1180 if (perform_gc) { 1181 if (space == NEW_SPACE) { 1182 CollectGarbage(NEW_SPACE, "failed to reserve space in the new space"); 1183 } else { 1184 if (counter > 1) { 1185 CollectAllGarbage( 1186 kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, 1187 "failed to reserve space in paged or large " 1188 "object space, trying to reduce memory footprint"); 1189 } else { 1190 CollectAllGarbage( 1191 kAbortIncrementalMarkingMask, 1192 "failed to reserve space in paged or large object space"); 1193 } 1194 } 1195 gc_performed = true; 1196 break; // Abort for-loop over spaces and retry. 1197 } 1198 } 1199 } 1200 1201 return !gc_performed; 1202 } 1203 1204 1205 void Heap::EnsureFromSpaceIsCommitted() { 1206 if (new_space_.CommitFromSpaceIfNeeded()) return; 1207 1208 // Committing memory to from space failed. 1209 // Memory is exhausted and we will die. 1210 V8::FatalProcessOutOfMemory("Committing semi space failed."); 1211 } 1212 1213 1214 void Heap::ClearNormalizedMapCaches() { 1215 if (isolate_->bootstrapper()->IsActive() && 1216 !incremental_marking()->IsMarking()) { 1217 return; 1218 } 1219 1220 Object* context = native_contexts_list(); 1221 while (!context->IsUndefined()) { 1222 // GC can happen when the context is not fully initialized, 1223 // so the cache can be undefined. 1224 Object* cache = 1225 Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX); 1226 if (!cache->IsUndefined()) { 1227 NormalizedMapCache::cast(cache)->Clear(); 1228 } 1229 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); 1230 } 1231 } 1232 1233 1234 void Heap::UpdateSurvivalStatistics(int start_new_space_size) { 1235 if (start_new_space_size == 0) return; 1236 1237 promotion_ratio_ = (static_cast<double>(promoted_objects_size_) / 1238 static_cast<double>(start_new_space_size) * 100); 1239 1240 if (previous_semi_space_copied_object_size_ > 0) { 1241 promotion_rate_ = 1242 (static_cast<double>(promoted_objects_size_) / 1243 static_cast<double>(previous_semi_space_copied_object_size_) * 100); 1244 } else { 1245 promotion_rate_ = 0; 1246 } 1247 1248 semi_space_copied_rate_ = 1249 (static_cast<double>(semi_space_copied_object_size_) / 1250 static_cast<double>(start_new_space_size) * 100); 1251 1252 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; 1253 tracer()->AddSurvivalRatio(survival_rate); 1254 if (survival_rate > kYoungSurvivalRateHighThreshold) { 1255 high_survival_rate_period_length_++; 1256 } else { 1257 high_survival_rate_period_length_ = 0; 1258 } 1259 } 1260 1261 bool Heap::PerformGarbageCollection( 1262 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { 1263 int freed_global_handles = 0; 1264 1265 if (collector != SCAVENGER) { 1266 PROFILE(isolate_, CodeMovingGCEvent()); 1267 } 1268 1269 #ifdef VERIFY_HEAP 1270 if (FLAG_verify_heap) { 1271 VerifyStringTable(this); 1272 } 1273 #endif 1274 1275 GCType gc_type = 1276 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; 1277 1278 { 1279 GCCallbacksScope scope(this); 1280 if (scope.CheckReenter()) { 1281 AllowHeapAllocation allow_allocation; 1282 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); 1283 VMState<EXTERNAL> state(isolate_); 1284 HandleScope handle_scope(isolate_); 1285 CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags); 1286 } 1287 } 1288 1289 EnsureFromSpaceIsCommitted(); 1290 1291 int start_new_space_size = Heap::new_space()->SizeAsInt(); 1292 1293 if (IsHighSurvivalRate()) { 1294 // We speed up the incremental marker if it is running so that it 1295 // does not fall behind the rate of promotion, which would cause a 1296 // constantly growing old space. 1297 incremental_marking()->NotifyOfHighPromotionRate(); 1298 } 1299 1300 { 1301 Heap::PretenuringScope pretenuring_scope(this); 1302 1303 if (collector == MARK_COMPACTOR) { 1304 UpdateOldGenerationAllocationCounter(); 1305 // Perform mark-sweep with optional compaction. 1306 MarkCompact(); 1307 old_gen_exhausted_ = false; 1308 old_generation_size_configured_ = true; 1309 // This should be updated before PostGarbageCollectionProcessing, which 1310 // can cause another GC. Take into account the objects promoted during GC. 1311 old_generation_allocation_counter_ += 1312 static_cast<size_t>(promoted_objects_size_); 1313 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); 1314 } else { 1315 Scavenge(); 1316 } 1317 1318 ProcessPretenuringFeedback(); 1319 } 1320 1321 UpdateSurvivalStatistics(start_new_space_size); 1322 ConfigureInitialOldGenerationSize(); 1323 1324 isolate_->counters()->objs_since_last_young()->Set(0); 1325 1326 if (collector != SCAVENGER) { 1327 // Callbacks that fire after this point might trigger nested GCs and 1328 // restart incremental marking, the assertion can't be moved down. 1329 DCHECK(incremental_marking()->IsStopped()); 1330 1331 // We finished a marking cycle. We can uncommit the marking deque until 1332 // we start marking again. 1333 mark_compact_collector()->marking_deque()->Uninitialize(); 1334 mark_compact_collector()->EnsureMarkingDequeIsCommitted( 1335 MarkCompactCollector::kMinMarkingDequeSize); 1336 } 1337 1338 gc_post_processing_depth_++; 1339 { 1340 AllowHeapAllocation allow_allocation; 1341 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); 1342 freed_global_handles = 1343 isolate_->global_handles()->PostGarbageCollectionProcessing( 1344 collector, gc_callback_flags); 1345 } 1346 gc_post_processing_depth_--; 1347 1348 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); 1349 1350 // Update relocatables. 1351 Relocatable::PostGarbageCollectionProcessing(isolate_); 1352 1353 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); 1354 double mutator_speed = static_cast<double>( 1355 tracer() 1356 ->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond()); 1357 intptr_t old_gen_size = PromotedSpaceSizeOfObjects(); 1358 if (collector == MARK_COMPACTOR) { 1359 // Register the amount of external allocated memory. 1360 amount_of_external_allocated_memory_at_last_global_gc_ = 1361 amount_of_external_allocated_memory_; 1362 SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); 1363 } else if (HasLowYoungGenerationAllocationRate() && 1364 old_generation_size_configured_) { 1365 DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); 1366 } 1367 1368 { 1369 GCCallbacksScope scope(this); 1370 if (scope.CheckReenter()) { 1371 AllowHeapAllocation allow_allocation; 1372 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); 1373 VMState<EXTERNAL> state(isolate_); 1374 HandleScope handle_scope(isolate_); 1375 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); 1376 } 1377 } 1378 1379 #ifdef VERIFY_HEAP 1380 if (FLAG_verify_heap) { 1381 VerifyStringTable(this); 1382 } 1383 #endif 1384 1385 return freed_global_handles > 0; 1386 } 1387 1388 1389 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { 1390 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { 1391 if (gc_type & gc_prologue_callbacks_[i].gc_type) { 1392 if (!gc_prologue_callbacks_[i].pass_isolate) { 1393 v8::GCCallback callback = reinterpret_cast<v8::GCCallback>( 1394 gc_prologue_callbacks_[i].callback); 1395 callback(gc_type, flags); 1396 } else { 1397 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); 1398 gc_prologue_callbacks_[i].callback(isolate, gc_type, flags); 1399 } 1400 } 1401 } 1402 } 1403 1404 1405 void Heap::CallGCEpilogueCallbacks(GCType gc_type, 1406 GCCallbackFlags gc_callback_flags) { 1407 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { 1408 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { 1409 if (!gc_epilogue_callbacks_[i].pass_isolate) { 1410 v8::GCCallback callback = reinterpret_cast<v8::GCCallback>( 1411 gc_epilogue_callbacks_[i].callback); 1412 callback(gc_type, gc_callback_flags); 1413 } else { 1414 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); 1415 gc_epilogue_callbacks_[i].callback(isolate, gc_type, gc_callback_flags); 1416 } 1417 } 1418 } 1419 } 1420 1421 1422 void Heap::MarkCompact() { 1423 PauseInlineAllocationObserversScope pause_observers(new_space()); 1424 1425 gc_state_ = MARK_COMPACT; 1426 LOG(isolate_, ResourceEvent("markcompact", "begin")); 1427 1428 uint64_t size_of_objects_before_gc = SizeOfObjects(); 1429 1430 mark_compact_collector()->Prepare(); 1431 1432 ms_count_++; 1433 1434 MarkCompactPrologue(); 1435 1436 mark_compact_collector()->CollectGarbage(); 1437 1438 LOG(isolate_, ResourceEvent("markcompact", "end")); 1439 1440 MarkCompactEpilogue(); 1441 1442 if (FLAG_allocation_site_pretenuring) { 1443 EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc); 1444 } 1445 } 1446 1447 1448 void Heap::MarkCompactEpilogue() { 1449 gc_state_ = NOT_IN_GC; 1450 1451 isolate_->counters()->objs_since_last_full()->Set(0); 1452 1453 incremental_marking()->Epilogue(); 1454 1455 PreprocessStackTraces(); 1456 } 1457 1458 1459 void Heap::MarkCompactPrologue() { 1460 // At any old GC clear the keyed lookup cache to enable collection of unused 1461 // maps. 1462 isolate_->keyed_lookup_cache()->Clear(); 1463 isolate_->context_slot_cache()->Clear(); 1464 isolate_->descriptor_lookup_cache()->Clear(); 1465 RegExpResultsCache::Clear(string_split_cache()); 1466 RegExpResultsCache::Clear(regexp_multiple_cache()); 1467 1468 isolate_->compilation_cache()->MarkCompactPrologue(); 1469 1470 CompletelyClearInstanceofCache(); 1471 1472 FlushNumberStringCache(); 1473 if (FLAG_cleanup_code_caches_at_gc) { 1474 polymorphic_code_cache()->set_cache(undefined_value()); 1475 } 1476 1477 ClearNormalizedMapCaches(); 1478 } 1479 1480 1481 #ifdef VERIFY_HEAP 1482 // Visitor class to verify pointers in code or data space do not point into 1483 // new space. 1484 class VerifyNonPointerSpacePointersVisitor : public ObjectVisitor { 1485 public: 1486 explicit VerifyNonPointerSpacePointersVisitor(Heap* heap) : heap_(heap) {} 1487 1488 void VisitPointers(Object** start, Object** end) override { 1489 for (Object** current = start; current < end; current++) { 1490 if ((*current)->IsHeapObject()) { 1491 CHECK(!heap_->InNewSpace(HeapObject::cast(*current))); 1492 } 1493 } 1494 } 1495 1496 private: 1497 Heap* heap_; 1498 }; 1499 1500 1501 static void VerifyNonPointerSpacePointers(Heap* heap) { 1502 // Verify that there are no pointers to new space in spaces where we 1503 // do not expect them. 1504 VerifyNonPointerSpacePointersVisitor v(heap); 1505 HeapObjectIterator code_it(heap->code_space()); 1506 for (HeapObject* object = code_it.Next(); object != NULL; 1507 object = code_it.Next()) 1508 object->Iterate(&v); 1509 } 1510 #endif // VERIFY_HEAP 1511 1512 1513 void Heap::CheckNewSpaceExpansionCriteria() { 1514 if (FLAG_experimental_new_space_growth_heuristic) { 1515 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && 1516 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { 1517 // Grow the size of new space if there is room to grow, and more than 10% 1518 // have survived the last scavenge. 1519 new_space_.Grow(); 1520 survived_since_last_expansion_ = 0; 1521 } 1522 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && 1523 survived_since_last_expansion_ > new_space_.TotalCapacity()) { 1524 // Grow the size of new space if there is room to grow, and enough data 1525 // has survived scavenge since the last expansion. 1526 new_space_.Grow(); 1527 survived_since_last_expansion_ = 0; 1528 } 1529 } 1530 1531 1532 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { 1533 return heap->InNewSpace(*p) && 1534 !HeapObject::cast(*p)->map_word().IsForwardingAddress(); 1535 } 1536 1537 1538 static bool IsUnmodifiedHeapObject(Object** p) { 1539 Object* object = *p; 1540 if (object->IsSmi()) return false; 1541 HeapObject* heap_object = HeapObject::cast(object); 1542 if (!object->IsJSObject()) return false; 1543 Object* obj_constructor = (JSObject::cast(object))->map()->GetConstructor(); 1544 if (!obj_constructor->IsJSFunction()) return false; 1545 JSFunction* constructor = JSFunction::cast(obj_constructor); 1546 if (!constructor->shared()->IsApiFunction()) return false; 1547 if (constructor != nullptr && 1548 constructor->initial_map() == heap_object->map()) { 1549 return true; 1550 } 1551 return false; 1552 } 1553 1554 1555 void Heap::ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page, 1556 StoreBufferEvent event) { 1557 heap->store_buffer_rebuilder_.Callback(page, event); 1558 } 1559 1560 1561 void PromotionQueue::Initialize() { 1562 // The last to-space page may be used for promotion queue. On promotion 1563 // conflict, we use the emergency stack. 1564 DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) == 1565 0); 1566 front_ = rear_ = 1567 reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd()); 1568 limit_ = reinterpret_cast<intptr_t*>( 1569 Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start()); 1570 emergency_stack_ = NULL; 1571 } 1572 1573 1574 void PromotionQueue::RelocateQueueHead() { 1575 DCHECK(emergency_stack_ == NULL); 1576 1577 Page* p = Page::FromAllocationTop(reinterpret_cast<Address>(rear_)); 1578 intptr_t* head_start = rear_; 1579 intptr_t* head_end = Min(front_, reinterpret_cast<intptr_t*>(p->area_end())); 1580 1581 int entries_count = 1582 static_cast<int>(head_end - head_start) / kEntrySizeInWords; 1583 1584 emergency_stack_ = new List<Entry>(2 * entries_count); 1585 1586 while (head_start != head_end) { 1587 int size = static_cast<int>(*(head_start++)); 1588 HeapObject* obj = reinterpret_cast<HeapObject*>(*(head_start++)); 1589 // New space allocation in SemiSpaceCopyObject marked the region 1590 // overlapping with promotion queue as uninitialized. 1591 MSAN_MEMORY_IS_INITIALIZED(&size, sizeof(size)); 1592 MSAN_MEMORY_IS_INITIALIZED(&obj, sizeof(obj)); 1593 emergency_stack_->Add(Entry(obj, size)); 1594 } 1595 rear_ = head_end; 1596 } 1597 1598 1599 class ScavengeWeakObjectRetainer : public WeakObjectRetainer { 1600 public: 1601 explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) {} 1602 1603 virtual Object* RetainAs(Object* object) { 1604 if (!heap_->InFromSpace(object)) { 1605 return object; 1606 } 1607 1608 MapWord map_word = HeapObject::cast(object)->map_word(); 1609 if (map_word.IsForwardingAddress()) { 1610 return map_word.ToForwardingAddress(); 1611 } 1612 return NULL; 1613 } 1614 1615 private: 1616 Heap* heap_; 1617 }; 1618 1619 1620 void Heap::Scavenge() { 1621 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE); 1622 RelocationLock relocation_lock(this); 1623 // There are soft limits in the allocation code, designed to trigger a mark 1624 // sweep collection by failing allocations. There is no sense in trying to 1625 // trigger one during scavenge: scavenges allocation should always succeed. 1626 AlwaysAllocateScope scope(isolate()); 1627 1628 // Bump-pointer allocations done during scavenge are not real allocations. 1629 // Pause the inline allocation steps. 1630 PauseInlineAllocationObserversScope pause_observers(new_space()); 1631 1632 #ifdef VERIFY_HEAP 1633 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this); 1634 #endif 1635 1636 gc_state_ = SCAVENGE; 1637 1638 // Implements Cheney's copying algorithm 1639 LOG(isolate_, ResourceEvent("scavenge", "begin")); 1640 1641 // Clear descriptor cache. 1642 isolate_->descriptor_lookup_cache()->Clear(); 1643 1644 // Used for updating survived_since_last_expansion_ at function end. 1645 intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); 1646 1647 scavenge_collector_->SelectScavengingVisitorsTable(); 1648 1649 array_buffer_tracker()->PrepareDiscoveryInNewSpace(); 1650 1651 // Flip the semispaces. After flipping, to space is empty, from space has 1652 // live objects. 1653 new_space_.Flip(); 1654 new_space_.ResetAllocationInfo(); 1655 1656 // We need to sweep newly copied objects which can be either in the 1657 // to space or promoted to the old generation. For to-space 1658 // objects, we treat the bottom of the to space as a queue. Newly 1659 // copied and unswept objects lie between a 'front' mark and the 1660 // allocation pointer. 1661 // 1662 // Promoted objects can go into various old-generation spaces, and 1663 // can be allocated internally in the spaces (from the free list). 1664 // We treat the top of the to space as a queue of addresses of 1665 // promoted objects. The addresses of newly promoted and unswept 1666 // objects lie between a 'front' mark and a 'rear' mark that is 1667 // updated as a side effect of promoting an object. 1668 // 1669 // There is guaranteed to be enough room at the top of the to space 1670 // for the addresses of promoted objects: every object promoted 1671 // frees up its size in bytes from the top of the new space, and 1672 // objects are at least one pointer in size. 1673 Address new_space_front = new_space_.ToSpaceStart(); 1674 promotion_queue_.Initialize(); 1675 1676 ScavengeVisitor scavenge_visitor(this); 1677 1678 if (FLAG_scavenge_reclaim_unmodified_objects) { 1679 isolate()->global_handles()->IdentifyWeakUnmodifiedObjects( 1680 &IsUnmodifiedHeapObject); 1681 } 1682 1683 { 1684 // Copy roots. 1685 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); 1686 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); 1687 } 1688 1689 { 1690 // Copy objects reachable from the old generation. 1691 GCTracer::Scope gc_scope(tracer(), 1692 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); 1693 StoreBufferRebuildScope scope(this, store_buffer(), 1694 &ScavengeStoreBufferCallback); 1695 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); 1696 } 1697 1698 { 1699 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); 1700 // Copy objects reachable from the encountered weak collections list. 1701 scavenge_visitor.VisitPointer(&encountered_weak_collections_); 1702 // Copy objects reachable from the encountered weak cells. 1703 scavenge_visitor.VisitPointer(&encountered_weak_cells_); 1704 } 1705 1706 { 1707 // Copy objects reachable from the code flushing candidates list. 1708 GCTracer::Scope gc_scope(tracer(), 1709 GCTracer::Scope::SCAVENGER_CODE_FLUSH_CANDIDATES); 1710 MarkCompactCollector* collector = mark_compact_collector(); 1711 if (collector->is_code_flushing_enabled()) { 1712 collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor); 1713 } 1714 } 1715 1716 { 1717 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE); 1718 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 1719 } 1720 1721 if (FLAG_scavenge_reclaim_unmodified_objects) { 1722 isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( 1723 &IsUnscavengedHeapObject); 1724 1725 isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots( 1726 &scavenge_visitor); 1727 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 1728 } else { 1729 GCTracer::Scope gc_scope(tracer(), 1730 GCTracer::Scope::SCAVENGER_OBJECT_GROUPS); 1731 while (isolate()->global_handles()->IterateObjectGroups( 1732 &scavenge_visitor, &IsUnscavengedHeapObject)) { 1733 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 1734 } 1735 isolate()->global_handles()->RemoveObjectGroups(); 1736 isolate()->global_handles()->RemoveImplicitRefGroups(); 1737 1738 isolate()->global_handles()->IdentifyNewSpaceWeakIndependentHandles( 1739 &IsUnscavengedHeapObject); 1740 1741 isolate()->global_handles()->IterateNewSpaceWeakIndependentRoots( 1742 &scavenge_visitor); 1743 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 1744 } 1745 1746 UpdateNewSpaceReferencesInExternalStringTable( 1747 &UpdateNewSpaceReferenceInExternalStringTableEntry); 1748 1749 promotion_queue_.Destroy(); 1750 1751 incremental_marking()->UpdateMarkingDequeAfterScavenge(); 1752 1753 ScavengeWeakObjectRetainer weak_object_retainer(this); 1754 ProcessYoungWeakReferences(&weak_object_retainer); 1755 1756 DCHECK(new_space_front == new_space_.top()); 1757 1758 // Set age mark. 1759 new_space_.set_age_mark(new_space_.top()); 1760 1761 array_buffer_tracker()->FreeDead(true); 1762 1763 // Update how much has survived scavenge. 1764 IncrementYoungSurvivorsCounter(static_cast<int>( 1765 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); 1766 1767 LOG(isolate_, ResourceEvent("scavenge", "end")); 1768 1769 gc_state_ = NOT_IN_GC; 1770 } 1771 1772 1773 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, 1774 Object** p) { 1775 MapWord first_word = HeapObject::cast(*p)->map_word(); 1776 1777 if (!first_word.IsForwardingAddress()) { 1778 // Unreachable external string can be finalized. 1779 heap->FinalizeExternalString(String::cast(*p)); 1780 return NULL; 1781 } 1782 1783 // String is still reachable. 1784 return String::cast(first_word.ToForwardingAddress()); 1785 } 1786 1787 1788 void Heap::UpdateNewSpaceReferencesInExternalStringTable( 1789 ExternalStringTableUpdaterCallback updater_func) { 1790 #ifdef VERIFY_HEAP 1791 if (FLAG_verify_heap) { 1792 external_string_table_.Verify(); 1793 } 1794 #endif 1795 1796 if (external_string_table_.new_space_strings_.is_empty()) return; 1797 1798 Object** start = &external_string_table_.new_space_strings_[0]; 1799 Object** end = start + external_string_table_.new_space_strings_.length(); 1800 Object** last = start; 1801 1802 for (Object** p = start; p < end; ++p) { 1803 DCHECK(InFromSpace(*p)); 1804 String* target = updater_func(this, p); 1805 1806 if (target == NULL) continue; 1807 1808 DCHECK(target->IsExternalString()); 1809 1810 if (InNewSpace(target)) { 1811 // String is still in new space. Update the table entry. 1812 *last = target; 1813 ++last; 1814 } else { 1815 // String got promoted. Move it to the old string list. 1816 external_string_table_.AddOldString(target); 1817 } 1818 } 1819 1820 DCHECK(last <= end); 1821 external_string_table_.ShrinkNewStrings(static_cast<int>(last - start)); 1822 } 1823 1824 1825 void Heap::UpdateReferencesInExternalStringTable( 1826 ExternalStringTableUpdaterCallback updater_func) { 1827 // Update old space string references. 1828 if (external_string_table_.old_space_strings_.length() > 0) { 1829 Object** start = &external_string_table_.old_space_strings_[0]; 1830 Object** end = start + external_string_table_.old_space_strings_.length(); 1831 for (Object** p = start; p < end; ++p) *p = updater_func(this, p); 1832 } 1833 1834 UpdateNewSpaceReferencesInExternalStringTable(updater_func); 1835 } 1836 1837 1838 void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { 1839 ProcessNativeContexts(retainer); 1840 ProcessAllocationSites(retainer); 1841 } 1842 1843 1844 void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { 1845 ProcessNativeContexts(retainer); 1846 } 1847 1848 1849 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { 1850 Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer); 1851 // Update the head of the list of contexts. 1852 set_native_contexts_list(head); 1853 } 1854 1855 1856 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { 1857 Object* allocation_site_obj = 1858 VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer); 1859 set_allocation_sites_list(allocation_site_obj); 1860 } 1861 1862 1863 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { 1864 DisallowHeapAllocation no_allocation_scope; 1865 Object* cur = allocation_sites_list(); 1866 bool marked = false; 1867 while (cur->IsAllocationSite()) { 1868 AllocationSite* casted = AllocationSite::cast(cur); 1869 if (casted->GetPretenureMode() == flag) { 1870 casted->ResetPretenureDecision(); 1871 casted->set_deopt_dependent_code(true); 1872 marked = true; 1873 RemoveAllocationSitePretenuringFeedback(casted); 1874 } 1875 cur = casted->weak_next(); 1876 } 1877 if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); 1878 } 1879 1880 1881 void Heap::EvaluateOldSpaceLocalPretenuring( 1882 uint64_t size_of_objects_before_gc) { 1883 uint64_t size_of_objects_after_gc = SizeOfObjects(); 1884 double old_generation_survival_rate = 1885 (static_cast<double>(size_of_objects_after_gc) * 100) / 1886 static_cast<double>(size_of_objects_before_gc); 1887 1888 if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) { 1889 // Too many objects died in the old generation, pretenuring of wrong 1890 // allocation sites may be the cause for that. We have to deopt all 1891 // dependent code registered in the allocation sites to re-evaluate 1892 // our pretenuring decisions. 1893 ResetAllAllocationSitesDependentCode(TENURED); 1894 if (FLAG_trace_pretenuring) { 1895 PrintF( 1896 "Deopt all allocation sites dependent code due to low survival " 1897 "rate in the old generation %f\n", 1898 old_generation_survival_rate); 1899 } 1900 } 1901 } 1902 1903 1904 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { 1905 DisallowHeapAllocation no_allocation; 1906 // All external strings are listed in the external string table. 1907 1908 class ExternalStringTableVisitorAdapter : public ObjectVisitor { 1909 public: 1910 explicit ExternalStringTableVisitorAdapter( 1911 v8::ExternalResourceVisitor* visitor) 1912 : visitor_(visitor) {} 1913 virtual void VisitPointers(Object** start, Object** end) { 1914 for (Object** p = start; p < end; p++) { 1915 DCHECK((*p)->IsExternalString()); 1916 visitor_->VisitExternalString( 1917 Utils::ToLocal(Handle<String>(String::cast(*p)))); 1918 } 1919 } 1920 1921 private: 1922 v8::ExternalResourceVisitor* visitor_; 1923 } external_string_table_visitor(visitor); 1924 1925 external_string_table_.Iterate(&external_string_table_visitor); 1926 } 1927 1928 1929 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, 1930 Address new_space_front) { 1931 do { 1932 SemiSpace::AssertValidRange(new_space_front, new_space_.top()); 1933 // The addresses new_space_front and new_space_.top() define a 1934 // queue of unprocessed copied objects. Process them until the 1935 // queue is empty. 1936 while (new_space_front != new_space_.top()) { 1937 if (!NewSpacePage::IsAtEnd(new_space_front)) { 1938 HeapObject* object = HeapObject::FromAddress(new_space_front); 1939 new_space_front += 1940 StaticScavengeVisitor::IterateBody(object->map(), object); 1941 } else { 1942 new_space_front = 1943 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); 1944 } 1945 } 1946 1947 // Promote and process all the to-be-promoted objects. 1948 { 1949 StoreBufferRebuildScope scope(this, store_buffer(), 1950 &ScavengeStoreBufferCallback); 1951 while (!promotion_queue()->is_empty()) { 1952 HeapObject* target; 1953 int size; 1954 promotion_queue()->remove(&target, &size); 1955 1956 // Promoted object might be already partially visited 1957 // during old space pointer iteration. Thus we search specifically 1958 // for pointers to from semispace instead of looking for pointers 1959 // to new space. 1960 DCHECK(!target->IsMap()); 1961 1962 IteratePointersToFromSpace(target, size, &Scavenger::ScavengeObject); 1963 } 1964 } 1965 1966 // Take another spin if there are now unswept objects in new space 1967 // (there are currently no more unswept promoted objects). 1968 } while (new_space_front != new_space_.top()); 1969 1970 return new_space_front; 1971 } 1972 1973 1974 STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) == 1975 0); // NOLINT 1976 STATIC_ASSERT((FixedTypedArrayBase::kDataOffset & kDoubleAlignmentMask) == 1977 0); // NOLINT 1978 #ifdef V8_HOST_ARCH_32_BIT 1979 STATIC_ASSERT((HeapNumber::kValueOffset & kDoubleAlignmentMask) != 1980 0); // NOLINT 1981 #endif 1982 1983 1984 int Heap::GetMaximumFillToAlign(AllocationAlignment alignment) { 1985 switch (alignment) { 1986 case kWordAligned: 1987 return 0; 1988 case kDoubleAligned: 1989 case kDoubleUnaligned: 1990 return kDoubleSize - kPointerSize; 1991 case kSimd128Unaligned: 1992 return kSimd128Size - kPointerSize; 1993 default: 1994 UNREACHABLE(); 1995 } 1996 return 0; 1997 } 1998 1999 2000 int Heap::GetFillToAlign(Address address, AllocationAlignment alignment) { 2001 intptr_t offset = OffsetFrom(address); 2002 if (alignment == kDoubleAligned && (offset & kDoubleAlignmentMask) != 0) 2003 return kPointerSize; 2004 if (alignment == kDoubleUnaligned && (offset & kDoubleAlignmentMask) == 0) 2005 return kDoubleSize - kPointerSize; // No fill if double is always aligned. 2006 if (alignment == kSimd128Unaligned) { 2007 return (kSimd128Size - (static_cast<int>(offset) + kPointerSize)) & 2008 kSimd128AlignmentMask; 2009 } 2010 return 0; 2011 } 2012 2013 2014 HeapObject* Heap::PrecedeWithFiller(HeapObject* object, int filler_size) { 2015 CreateFillerObjectAt(object->address(), filler_size); 2016 return HeapObject::FromAddress(object->address() + filler_size); 2017 } 2018 2019 2020 HeapObject* Heap::AlignWithFiller(HeapObject* object, int object_size, 2021 int allocation_size, 2022 AllocationAlignment alignment) { 2023 int filler_size = allocation_size - object_size; 2024 DCHECK(filler_size > 0); 2025 int pre_filler = GetFillToAlign(object->address(), alignment); 2026 if (pre_filler) { 2027 object = PrecedeWithFiller(object, pre_filler); 2028 filler_size -= pre_filler; 2029 } 2030 if (filler_size) 2031 CreateFillerObjectAt(object->address() + object_size, filler_size); 2032 return object; 2033 } 2034 2035 2036 HeapObject* Heap::DoubleAlignForDeserialization(HeapObject* object, int size) { 2037 return AlignWithFiller(object, size - kPointerSize, size, kDoubleAligned); 2038 } 2039 2040 2041 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) { 2042 return array_buffer_tracker()->RegisterNew(buffer); 2043 } 2044 2045 2046 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) { 2047 return array_buffer_tracker()->Unregister(buffer); 2048 } 2049 2050 2051 void Heap::ConfigureInitialOldGenerationSize() { 2052 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { 2053 old_generation_allocation_limit_ = 2054 Max(kMinimumOldGenerationAllocationLimit, 2055 static_cast<intptr_t>( 2056 static_cast<double>(old_generation_allocation_limit_) * 2057 (tracer()->AverageSurvivalRatio() / 100))); 2058 } 2059 } 2060 2061 2062 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, 2063 int instance_size) { 2064 Object* result = nullptr; 2065 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE); 2066 if (!allocation.To(&result)) return allocation; 2067 2068 // Map::cast cannot be used due to uninitialized map field. 2069 reinterpret_cast<Map*>(result)->set_map( 2070 reinterpret_cast<Map*>(root(kMetaMapRootIndex))); 2071 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); 2072 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); 2073 // Initialize to only containing tagged fields. 2074 reinterpret_cast<Map*>(result)->set_visitor_id( 2075 StaticVisitorBase::GetVisitorId(instance_type, instance_size, false)); 2076 if (FLAG_unbox_double_fields) { 2077 reinterpret_cast<Map*>(result) 2078 ->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); 2079 } 2080 reinterpret_cast<Map*>(result)->clear_unused(); 2081 reinterpret_cast<Map*>(result) 2082 ->set_inobject_properties_or_constructor_function_index(0); 2083 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); 2084 reinterpret_cast<Map*>(result)->set_bit_field(0); 2085 reinterpret_cast<Map*>(result)->set_bit_field2(0); 2086 int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | 2087 Map::OwnsDescriptors::encode(true) | 2088 Map::ConstructionCounter::encode(Map::kNoSlackTracking); 2089 reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3); 2090 reinterpret_cast<Map*>(result)->set_weak_cell_cache(Smi::FromInt(0)); 2091 return result; 2092 } 2093 2094 2095 AllocationResult Heap::AllocateMap(InstanceType instance_type, 2096 int instance_size, 2097 ElementsKind elements_kind) { 2098 HeapObject* result = nullptr; 2099 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE); 2100 if (!allocation.To(&result)) return allocation; 2101 2102 result->set_map_no_write_barrier(meta_map()); 2103 Map* map = Map::cast(result); 2104 map->set_instance_type(instance_type); 2105 map->set_prototype(null_value(), SKIP_WRITE_BARRIER); 2106 map->set_constructor_or_backpointer(null_value(), SKIP_WRITE_BARRIER); 2107 map->set_instance_size(instance_size); 2108 map->clear_unused(); 2109 map->set_inobject_properties_or_constructor_function_index(0); 2110 map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER); 2111 map->set_dependent_code(DependentCode::cast(empty_fixed_array()), 2112 SKIP_WRITE_BARRIER); 2113 map->set_weak_cell_cache(Smi::FromInt(0)); 2114 map->set_raw_transitions(Smi::FromInt(0)); 2115 map->set_unused_property_fields(0); 2116 map->set_instance_descriptors(empty_descriptor_array()); 2117 if (FLAG_unbox_double_fields) { 2118 map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); 2119 } 2120 // Must be called only after |instance_type|, |instance_size| and 2121 // |layout_descriptor| are set. 2122 map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map)); 2123 map->set_bit_field(0); 2124 map->set_bit_field2(1 << Map::kIsExtensible); 2125 int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | 2126 Map::OwnsDescriptors::encode(true) | 2127 Map::ConstructionCounter::encode(Map::kNoSlackTracking); 2128 map->set_bit_field3(bit_field3); 2129 map->set_elements_kind(elements_kind); 2130 map->set_new_target_is_base(true); 2131 2132 return map; 2133 } 2134 2135 2136 AllocationResult Heap::AllocateFillerObject(int size, bool double_align, 2137 AllocationSpace space) { 2138 HeapObject* obj = nullptr; 2139 { 2140 AllocationAlignment align = double_align ? kDoubleAligned : kWordAligned; 2141 AllocationResult allocation = AllocateRaw(size, space, align); 2142 if (!allocation.To(&obj)) return allocation; 2143 } 2144 #ifdef DEBUG 2145 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); 2146 DCHECK(chunk->owner()->identity() == space); 2147 #endif 2148 CreateFillerObjectAt(obj->address(), size); 2149 return obj; 2150 } 2151 2152 2153 const Heap::StringTypeTable Heap::string_type_table[] = { 2154 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ 2155 { type, size, k##camel_name##MapRootIndex } \ 2156 , 2157 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) 2158 #undef STRING_TYPE_ELEMENT 2159 }; 2160 2161 2162 const Heap::ConstantStringTable Heap::constant_string_table[] = { 2163 {"", kempty_stringRootIndex}, 2164 #define CONSTANT_STRING_ELEMENT(name, contents) \ 2165 { contents, k##name##RootIndex } \ 2166 , 2167 INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT) 2168 #undef CONSTANT_STRING_ELEMENT 2169 }; 2170 2171 2172 const Heap::StructTable Heap::struct_table[] = { 2173 #define STRUCT_TABLE_ELEMENT(NAME, Name, name) \ 2174 { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex } \ 2175 , 2176 STRUCT_LIST(STRUCT_TABLE_ELEMENT) 2177 #undef STRUCT_TABLE_ELEMENT 2178 }; 2179 2180 2181 bool Heap::CreateInitialMaps() { 2182 HeapObject* obj = nullptr; 2183 { 2184 AllocationResult allocation = AllocatePartialMap(MAP_TYPE, Map::kSize); 2185 if (!allocation.To(&obj)) return false; 2186 } 2187 // Map::cast cannot be used due to uninitialized map field. 2188 Map* new_meta_map = reinterpret_cast<Map*>(obj); 2189 set_meta_map(new_meta_map); 2190 new_meta_map->set_map(new_meta_map); 2191 2192 { // Partial map allocation 2193 #define ALLOCATE_PARTIAL_MAP(instance_type, size, field_name) \ 2194 { \ 2195 Map* map; \ 2196 if (!AllocatePartialMap((instance_type), (size)).To(&map)) return false; \ 2197 set_##field_name##_map(map); \ 2198 } 2199 2200 ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel, fixed_array); 2201 ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, undefined); 2202 ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, null); 2203 2204 #undef ALLOCATE_PARTIAL_MAP 2205 } 2206 2207 // Allocate the empty array. 2208 { 2209 AllocationResult allocation = AllocateEmptyFixedArray(); 2210 if (!allocation.To(&obj)) return false; 2211 } 2212 set_empty_fixed_array(FixedArray::cast(obj)); 2213 2214 { 2215 AllocationResult allocation = Allocate(null_map(), OLD_SPACE); 2216 if (!allocation.To(&obj)) return false; 2217 } 2218 set_null_value(Oddball::cast(obj)); 2219 Oddball::cast(obj)->set_kind(Oddball::kNull); 2220 2221 { 2222 AllocationResult allocation = Allocate(undefined_map(), OLD_SPACE); 2223 if (!allocation.To(&obj)) return false; 2224 } 2225 set_undefined_value(Oddball::cast(obj)); 2226 Oddball::cast(obj)->set_kind(Oddball::kUndefined); 2227 DCHECK(!InNewSpace(undefined_value())); 2228 2229 // Set preliminary exception sentinel value before actually initializing it. 2230 set_exception(null_value()); 2231 2232 // Allocate the empty descriptor array. 2233 { 2234 AllocationResult allocation = AllocateEmptyFixedArray(); 2235 if (!allocation.To(&obj)) return false; 2236 } 2237 set_empty_descriptor_array(DescriptorArray::cast(obj)); 2238 2239 // Fix the instance_descriptors for the existing maps. 2240 meta_map()->set_code_cache(empty_fixed_array()); 2241 meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); 2242 meta_map()->set_raw_transitions(Smi::FromInt(0)); 2243 meta_map()->set_instance_descriptors(empty_descriptor_array()); 2244 if (FLAG_unbox_double_fields) { 2245 meta_map()->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); 2246 } 2247 2248 fixed_array_map()->set_code_cache(empty_fixed_array()); 2249 fixed_array_map()->set_dependent_code( 2250 DependentCode::cast(empty_fixed_array())); 2251 fixed_array_map()->set_raw_transitions(Smi::FromInt(0)); 2252 fixed_array_map()->set_instance_descriptors(empty_descriptor_array()); 2253 if (FLAG_unbox_double_fields) { 2254 fixed_array_map()->set_layout_descriptor( 2255 LayoutDescriptor::FastPointerLayout()); 2256 } 2257 2258 undefined_map()->set_code_cache(empty_fixed_array()); 2259 undefined_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); 2260 undefined_map()->set_raw_transitions(Smi::FromInt(0)); 2261 undefined_map()->set_instance_descriptors(empty_descriptor_array()); 2262 if (FLAG_unbox_double_fields) { 2263 undefined_map()->set_layout_descriptor( 2264 LayoutDescriptor::FastPointerLayout()); 2265 } 2266 2267 null_map()->set_code_cache(empty_fixed_array()); 2268 null_map()->set_dependent_code(DependentCode::cast(empty_fixed_array())); 2269 null_map()->set_raw_transitions(Smi::FromInt(0)); 2270 null_map()->set_instance_descriptors(empty_descriptor_array()); 2271 if (FLAG_unbox_double_fields) { 2272 null_map()->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); 2273 } 2274 2275 // Fix prototype object for existing maps. 2276 meta_map()->set_prototype(null_value()); 2277 meta_map()->set_constructor_or_backpointer(null_value()); 2278 2279 fixed_array_map()->set_prototype(null_value()); 2280 fixed_array_map()->set_constructor_or_backpointer(null_value()); 2281 2282 undefined_map()->set_prototype(null_value()); 2283 undefined_map()->set_constructor_or_backpointer(null_value()); 2284 2285 null_map()->set_prototype(null_value()); 2286 null_map()->set_constructor_or_backpointer(null_value()); 2287 2288 { // Map allocation 2289 #define ALLOCATE_MAP(instance_type, size, field_name) \ 2290 { \ 2291 Map* map; \ 2292 if (!AllocateMap((instance_type), size).To(&map)) return false; \ 2293 set_##field_name##_map(map); \ 2294 } 2295 2296 #define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \ 2297 ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name) 2298 2299 #define ALLOCATE_PRIMITIVE_MAP(instance_type, size, field_name, \ 2300 constructor_function_index) \ 2301 { \ 2302 ALLOCATE_MAP((instance_type), (size), field_name); \ 2303 field_name##_map()->SetConstructorFunctionIndex( \ 2304 (constructor_function_index)); \ 2305 } 2306 2307 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array) 2308 DCHECK(fixed_array_map() != fixed_cow_array_map()); 2309 2310 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info) 2311 ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number, 2312 Context::NUMBER_FUNCTION_INDEX) 2313 ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize, 2314 mutable_heap_number) 2315 ALLOCATE_PRIMITIVE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol, 2316 Context::SYMBOL_FUNCTION_INDEX) 2317 #define ALLOCATE_SIMD128_MAP(TYPE, Type, type, lane_count, lane_type) \ 2318 ALLOCATE_PRIMITIVE_MAP(SIMD128_VALUE_TYPE, Type::kSize, type, \ 2319 Context::TYPE##_FUNCTION_INDEX) 2320 SIMD128_TYPES(ALLOCATE_SIMD128_MAP) 2321 #undef ALLOCATE_SIMD128_MAP 2322 ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign) 2323 2324 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole); 2325 ALLOCATE_PRIMITIVE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean, 2326 Context::BOOLEAN_FUNCTION_INDEX); 2327 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized); 2328 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, arguments_marker); 2329 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel); 2330 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception); 2331 ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception); 2332 2333 for (unsigned i = 0; i < arraysize(string_type_table); i++) { 2334 const StringTypeTable& entry = string_type_table[i]; 2335 { 2336 AllocationResult allocation = AllocateMap(entry.type, entry.size); 2337 if (!allocation.To(&obj)) return false; 2338 } 2339 Map* map = Map::cast(obj); 2340 map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX); 2341 // Mark cons string maps as unstable, because their objects can change 2342 // maps during GC. 2343 if (StringShape(entry.type).IsCons()) map->mark_unstable(); 2344 roots_[entry.index] = map; 2345 } 2346 2347 { // Create a separate external one byte string map for native sources. 2348 AllocationResult allocation = AllocateMap(EXTERNAL_ONE_BYTE_STRING_TYPE, 2349 ExternalOneByteString::kSize); 2350 if (!allocation.To(&obj)) return false; 2351 Map* map = Map::cast(obj); 2352 map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX); 2353 set_native_source_string_map(map); 2354 } 2355 2356 ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array) 2357 ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array) 2358 ALLOCATE_VARSIZE_MAP(BYTECODE_ARRAY_TYPE, bytecode_array) 2359 ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space) 2360 2361 #define ALLOCATE_FIXED_TYPED_ARRAY_MAP(Type, type, TYPE, ctype, size) \ 2362 ALLOCATE_VARSIZE_MAP(FIXED_##TYPE##_ARRAY_TYPE, fixed_##type##_array) 2363 2364 TYPED_ARRAYS(ALLOCATE_FIXED_TYPED_ARRAY_MAP) 2365 #undef ALLOCATE_FIXED_TYPED_ARRAY_MAP 2366 2367 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements) 2368 2369 ALLOCATE_VARSIZE_MAP(CODE_TYPE, code) 2370 2371 ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell) 2372 ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell) 2373 ALLOCATE_MAP(WEAK_CELL_TYPE, WeakCell::kSize, weak_cell) 2374 ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler) 2375 ALLOCATE_MAP(FILLER_TYPE, 2 * kPointerSize, two_pointer_filler) 2376 2377 ALLOCATE_VARSIZE_MAP(TRANSITION_ARRAY_TYPE, transition_array) 2378 2379 for (unsigned i = 0; i < arraysize(struct_table); i++) { 2380 const StructTable& entry = struct_table[i]; 2381 Map* map; 2382 if (!AllocateMap(entry.type, entry.size).To(&map)) return false; 2383 roots_[entry.index] = map; 2384 } 2385 2386 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table) 2387 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, ordered_hash_table) 2388 2389 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context) 2390 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context) 2391 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, with_context) 2392 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, block_context) 2393 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_context) 2394 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, script_context) 2395 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, script_context_table) 2396 2397 ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, native_context) 2398 native_context_map()->set_dictionary_map(true); 2399 native_context_map()->set_visitor_id( 2400 StaticVisitorBase::kVisitNativeContext); 2401 2402 ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize, 2403 shared_function_info) 2404 2405 ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize, message_object) 2406 ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize, external) 2407 external_map()->set_is_extensible(false); 2408 #undef ALLOCATE_PRIMITIVE_MAP 2409 #undef ALLOCATE_VARSIZE_MAP 2410 #undef ALLOCATE_MAP 2411 } 2412 2413 { // Empty arrays 2414 { 2415 ByteArray* byte_array; 2416 if (!AllocateByteArray(0, TENURED).To(&byte_array)) return false; 2417 set_empty_byte_array(byte_array); 2418 2419 BytecodeArray* bytecode_array = nullptr; 2420 AllocationResult allocation = 2421 AllocateBytecodeArray(0, nullptr, 0, 0, empty_fixed_array()); 2422 if (!allocation.To(&bytecode_array)) { 2423 return false; 2424 } 2425 set_empty_bytecode_array(bytecode_array); 2426 } 2427 2428 #define ALLOCATE_EMPTY_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \ 2429 { \ 2430 FixedTypedArrayBase* obj; \ 2431 if (!AllocateEmptyFixedTypedArray(kExternal##Type##Array).To(&obj)) \ 2432 return false; \ 2433 set_empty_fixed_##type##_array(obj); \ 2434 } 2435 2436 TYPED_ARRAYS(ALLOCATE_EMPTY_FIXED_TYPED_ARRAY) 2437 #undef ALLOCATE_EMPTY_FIXED_TYPED_ARRAY 2438 } 2439 DCHECK(!InNewSpace(empty_fixed_array())); 2440 return true; 2441 } 2442 2443 2444 AllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode, 2445 PretenureFlag pretenure) { 2446 // Statically ensure that it is safe to allocate heap numbers in paged 2447 // spaces. 2448 int size = HeapNumber::kSize; 2449 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxRegularHeapObjectSize); 2450 2451 AllocationSpace space = SelectSpace(pretenure); 2452 2453 HeapObject* result = nullptr; 2454 { 2455 AllocationResult allocation = AllocateRaw(size, space, kDoubleUnaligned); 2456 if (!allocation.To(&result)) return allocation; 2457 } 2458 2459 Map* map = mode == MUTABLE ? mutable_heap_number_map() : heap_number_map(); 2460 HeapObject::cast(result)->set_map_no_write_barrier(map); 2461 HeapNumber::cast(result)->set_value(value); 2462 return result; 2463 } 2464 2465 #define SIMD_ALLOCATE_DEFINITION(TYPE, Type, type, lane_count, lane_type) \ 2466 AllocationResult Heap::Allocate##Type(lane_type lanes[lane_count], \ 2467 PretenureFlag pretenure) { \ 2468 int size = Type::kSize; \ 2469 STATIC_ASSERT(Type::kSize <= Page::kMaxRegularHeapObjectSize); \ 2470 \ 2471 AllocationSpace space = SelectSpace(pretenure); \ 2472 \ 2473 HeapObject* result = nullptr; \ 2474 { \ 2475 AllocationResult allocation = \ 2476 AllocateRaw(size, space, kSimd128Unaligned); \ 2477 if (!allocation.To(&result)) return allocation; \ 2478 } \ 2479 \ 2480 result->set_map_no_write_barrier(type##_map()); \ 2481 Type* instance = Type::cast(result); \ 2482 for (int i = 0; i < lane_count; i++) { \ 2483 instance->set_lane(i, lanes[i]); \ 2484 } \ 2485 return result; \ 2486 } 2487 SIMD128_TYPES(SIMD_ALLOCATE_DEFINITION) 2488 #undef SIMD_ALLOCATE_DEFINITION 2489 2490 2491 AllocationResult Heap::AllocateCell(Object* value) { 2492 int size = Cell::kSize; 2493 STATIC_ASSERT(Cell::kSize <= Page::kMaxRegularHeapObjectSize); 2494 2495 HeapObject* result = nullptr; 2496 { 2497 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 2498 if (!allocation.To(&result)) return allocation; 2499 } 2500 result->set_map_no_write_barrier(cell_map()); 2501 Cell::cast(result)->set_value(value); 2502 return result; 2503 } 2504 2505 2506 AllocationResult Heap::AllocatePropertyCell() { 2507 int size = PropertyCell::kSize; 2508 STATIC_ASSERT(PropertyCell::kSize <= Page::kMaxRegularHeapObjectSize); 2509 2510 HeapObject* result = nullptr; 2511 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 2512 if (!allocation.To(&result)) return allocation; 2513 2514 result->set_map_no_write_barrier(global_property_cell_map()); 2515 PropertyCell* cell = PropertyCell::cast(result); 2516 cell->set_dependent_code(DependentCode::cast(empty_fixed_array()), 2517 SKIP_WRITE_BARRIER); 2518 cell->set_property_details(PropertyDetails(Smi::FromInt(0))); 2519 cell->set_value(the_hole_value()); 2520 return result; 2521 } 2522 2523 2524 AllocationResult Heap::AllocateWeakCell(HeapObject* value) { 2525 int size = WeakCell::kSize; 2526 STATIC_ASSERT(WeakCell::kSize <= Page::kMaxRegularHeapObjectSize); 2527 HeapObject* result = nullptr; 2528 { 2529 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 2530 if (!allocation.To(&result)) return allocation; 2531 } 2532 result->set_map_no_write_barrier(weak_cell_map()); 2533 WeakCell::cast(result)->initialize(value); 2534 WeakCell::cast(result)->clear_next(the_hole_value()); 2535 return result; 2536 } 2537 2538 2539 AllocationResult Heap::AllocateTransitionArray(int capacity) { 2540 DCHECK(capacity > 0); 2541 HeapObject* raw_array = nullptr; 2542 { 2543 AllocationResult allocation = AllocateRawFixedArray(capacity, TENURED); 2544 if (!allocation.To(&raw_array)) return allocation; 2545 } 2546 raw_array->set_map_no_write_barrier(transition_array_map()); 2547 TransitionArray* array = TransitionArray::cast(raw_array); 2548 array->set_length(capacity); 2549 MemsetPointer(array->data_start(), undefined_value(), capacity); 2550 return array; 2551 } 2552 2553 2554 void Heap::CreateApiObjects() { 2555 HandleScope scope(isolate()); 2556 Factory* factory = isolate()->factory(); 2557 Handle<Map> new_neander_map = 2558 factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 2559 2560 // Don't use Smi-only elements optimizations for objects with the neander 2561 // map. There are too many cases where element values are set directly with a 2562 // bottleneck to trap the Smi-only -> fast elements transition, and there 2563 // appears to be no benefit for optimize this case. 2564 new_neander_map->set_elements_kind(TERMINAL_FAST_ELEMENTS_KIND); 2565 set_neander_map(*new_neander_map); 2566 2567 Handle<JSObject> listeners = factory->NewNeanderObject(); 2568 Handle<FixedArray> elements = factory->NewFixedArray(2); 2569 elements->set(0, Smi::FromInt(0)); 2570 listeners->set_elements(*elements); 2571 set_message_listeners(*listeners); 2572 } 2573 2574 2575 void Heap::CreateJSEntryStub() { 2576 JSEntryStub stub(isolate(), StackFrame::ENTRY); 2577 set_js_entry_code(*stub.GetCode()); 2578 } 2579 2580 2581 void Heap::CreateJSConstructEntryStub() { 2582 JSEntryStub stub(isolate(), StackFrame::ENTRY_CONSTRUCT); 2583 set_js_construct_entry_code(*stub.GetCode()); 2584 } 2585 2586 2587 void Heap::CreateFixedStubs() { 2588 // Here we create roots for fixed stubs. They are needed at GC 2589 // for cooking and uncooking (check out frames.cc). 2590 // The eliminates the need for doing dictionary lookup in the 2591 // stub cache for these stubs. 2592 HandleScope scope(isolate()); 2593 2594 // Create stubs that should be there, so we don't unexpectedly have to 2595 // create them if we need them during the creation of another stub. 2596 // Stub creation mixes raw pointers and handles in an unsafe manner so 2597 // we cannot create stubs while we are creating stubs. 2598 CodeStub::GenerateStubsAheadOfTime(isolate()); 2599 2600 // MacroAssembler::Abort calls (usually enabled with --debug-code) depend on 2601 // CEntryStub, so we need to call GenerateStubsAheadOfTime before JSEntryStub 2602 // is created. 2603 2604 // gcc-4.4 has problem generating correct code of following snippet: 2605 // { JSEntryStub stub; 2606 // js_entry_code_ = *stub.GetCode(); 2607 // } 2608 // { JSConstructEntryStub stub; 2609 // js_construct_entry_code_ = *stub.GetCode(); 2610 // } 2611 // To workaround the problem, make separate functions without inlining. 2612 Heap::CreateJSEntryStub(); 2613 Heap::CreateJSConstructEntryStub(); 2614 } 2615 2616 2617 void Heap::CreateInitialObjects() { 2618 HandleScope scope(isolate()); 2619 Factory* factory = isolate()->factory(); 2620 2621 // The -0 value must be set before NewNumber works. 2622 set_minus_zero_value(*factory->NewHeapNumber(-0.0, IMMUTABLE, TENURED)); 2623 DCHECK(std::signbit(minus_zero_value()->Number()) != 0); 2624 2625 set_nan_value(*factory->NewHeapNumber( 2626 std::numeric_limits<double>::quiet_NaN(), IMMUTABLE, TENURED)); 2627 set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE, TENURED)); 2628 set_minus_infinity_value( 2629 *factory->NewHeapNumber(-V8_INFINITY, IMMUTABLE, TENURED)); 2630 2631 // The hole has not been created yet, but we want to put something 2632 // predictable in the gaps in the string table, so lets make that Smi zero. 2633 set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0))); 2634 2635 // Allocate initial string table. 2636 set_string_table(*StringTable::New(isolate(), kInitialStringTableSize)); 2637 2638 // Finish initializing oddballs after creating the string table. 2639 Oddball::Initialize(isolate(), factory->undefined_value(), "undefined", 2640 factory->nan_value(), "undefined", Oddball::kUndefined); 2641 2642 // Initialize the null_value. 2643 Oddball::Initialize(isolate(), factory->null_value(), "null", 2644 handle(Smi::FromInt(0), isolate()), "object", 2645 Oddball::kNull); 2646 2647 set_true_value(*factory->NewOddball(factory->boolean_map(), "true", 2648 handle(Smi::FromInt(1), isolate()), 2649 "boolean", Oddball::kTrue)); 2650 2651 set_false_value(*factory->NewOddball(factory->boolean_map(), "false", 2652 handle(Smi::FromInt(0), isolate()), 2653 "boolean", Oddball::kFalse)); 2654 2655 set_the_hole_value(*factory->NewOddball(factory->the_hole_map(), "hole", 2656 handle(Smi::FromInt(-1), isolate()), 2657 "undefined", Oddball::kTheHole)); 2658 2659 set_uninitialized_value( 2660 *factory->NewOddball(factory->uninitialized_map(), "uninitialized", 2661 handle(Smi::FromInt(-1), isolate()), "undefined", 2662 Oddball::kUninitialized)); 2663 2664 set_arguments_marker( 2665 *factory->NewOddball(factory->arguments_marker_map(), "arguments_marker", 2666 handle(Smi::FromInt(-4), isolate()), "undefined", 2667 Oddball::kArgumentMarker)); 2668 2669 set_no_interceptor_result_sentinel(*factory->NewOddball( 2670 factory->no_interceptor_result_sentinel_map(), 2671 "no_interceptor_result_sentinel", handle(Smi::FromInt(-2), isolate()), 2672 "undefined", Oddball::kOther)); 2673 2674 set_termination_exception(*factory->NewOddball( 2675 factory->termination_exception_map(), "termination_exception", 2676 handle(Smi::FromInt(-3), isolate()), "undefined", Oddball::kOther)); 2677 2678 set_exception(*factory->NewOddball(factory->exception_map(), "exception", 2679 handle(Smi::FromInt(-5), isolate()), 2680 "undefined", Oddball::kException)); 2681 2682 for (unsigned i = 0; i < arraysize(constant_string_table); i++) { 2683 Handle<String> str = 2684 factory->InternalizeUtf8String(constant_string_table[i].contents); 2685 roots_[constant_string_table[i].index] = *str; 2686 } 2687 2688 // The {hidden_string} is special because it is an empty string, but does not 2689 // match any string (even the {empty_string}) when looked up in properties. 2690 // Allocate the hidden string which is used to identify the hidden properties 2691 // in JSObjects. The hash code has a special value so that it will not match 2692 // the empty string when searching for the property. It cannot be part of the 2693 // loop above because it needs to be allocated manually with the special 2694 // hash code in place. The hash code for the hidden_string is zero to ensure 2695 // that it will always be at the first entry in property descriptors. 2696 set_hidden_string(*factory->NewOneByteInternalizedString( 2697 OneByteVector("", 0), String::kEmptyStringHash)); 2698 2699 // Create the code_stubs dictionary. The initial size is set to avoid 2700 // expanding the dictionary during bootstrapping. 2701 set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128)); 2702 2703 // Create the non_monomorphic_cache used in stub-cache.cc. The initial size 2704 // is set to avoid expanding the dictionary during bootstrapping. 2705 set_non_monomorphic_cache(*UnseededNumberDictionary::New(isolate(), 64)); 2706 2707 set_polymorphic_code_cache(PolymorphicCodeCache::cast( 2708 *factory->NewStruct(POLYMORPHIC_CODE_CACHE_TYPE))); 2709 2710 set_instanceof_cache_function(Smi::FromInt(0)); 2711 set_instanceof_cache_map(Smi::FromInt(0)); 2712 set_instanceof_cache_answer(Smi::FromInt(0)); 2713 2714 { 2715 HandleScope scope(isolate()); 2716 #define SYMBOL_INIT(name) \ 2717 { \ 2718 Handle<String> name##d = factory->NewStringFromStaticChars(#name); \ 2719 Handle<Symbol> symbol(isolate()->factory()->NewPrivateSymbol()); \ 2720 symbol->set_name(*name##d); \ 2721 roots_[k##name##RootIndex] = *symbol; \ 2722 } 2723 PRIVATE_SYMBOL_LIST(SYMBOL_INIT) 2724 #undef SYMBOL_INIT 2725 } 2726 2727 { 2728 HandleScope scope(isolate()); 2729 #define SYMBOL_INIT(name, description) \ 2730 Handle<Symbol> name = factory->NewSymbol(); \ 2731 Handle<String> name##d = factory->NewStringFromStaticChars(#description); \ 2732 name->set_name(*name##d); \ 2733 roots_[k##name##RootIndex] = *name; 2734 PUBLIC_SYMBOL_LIST(SYMBOL_INIT) 2735 #undef SYMBOL_INIT 2736 2737 #define SYMBOL_INIT(name, description) \ 2738 Handle<Symbol> name = factory->NewSymbol(); \ 2739 Handle<String> name##d = factory->NewStringFromStaticChars(#description); \ 2740 name->set_is_well_known_symbol(true); \ 2741 name->set_name(*name##d); \ 2742 roots_[k##name##RootIndex] = *name; 2743 WELL_KNOWN_SYMBOL_LIST(SYMBOL_INIT) 2744 #undef SYMBOL_INIT 2745 } 2746 2747 CreateFixedStubs(); 2748 2749 // Allocate the dictionary of intrinsic function names. 2750 Handle<NameDictionary> intrinsic_names = 2751 NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED); 2752 Runtime::InitializeIntrinsicFunctionNames(isolate(), intrinsic_names); 2753 set_intrinsic_function_names(*intrinsic_names); 2754 2755 Handle<NameDictionary> empty_properties_dictionary = 2756 NameDictionary::New(isolate(), 0, TENURED); 2757 empty_properties_dictionary->SetRequiresCopyOnCapacityChange(); 2758 set_empty_properties_dictionary(*empty_properties_dictionary); 2759 2760 set_number_string_cache( 2761 *factory->NewFixedArray(kInitialNumberStringCacheSize * 2, TENURED)); 2762 2763 // Allocate cache for single character one byte strings. 2764 set_single_character_string_cache( 2765 *factory->NewFixedArray(String::kMaxOneByteCharCode + 1, TENURED)); 2766 2767 // Allocate cache for string split and regexp-multiple. 2768 set_string_split_cache(*factory->NewFixedArray( 2769 RegExpResultsCache::kRegExpResultsCacheSize, TENURED)); 2770 set_regexp_multiple_cache(*factory->NewFixedArray( 2771 RegExpResultsCache::kRegExpResultsCacheSize, TENURED)); 2772 2773 // Allocate cache for external strings pointing to native source code. 2774 set_natives_source_cache( 2775 *factory->NewFixedArray(Natives::GetBuiltinsCount())); 2776 2777 set_experimental_natives_source_cache( 2778 *factory->NewFixedArray(ExperimentalNatives::GetBuiltinsCount())); 2779 2780 set_extra_natives_source_cache( 2781 *factory->NewFixedArray(ExtraNatives::GetBuiltinsCount())); 2782 2783 set_experimental_extra_natives_source_cache( 2784 *factory->NewFixedArray(ExperimentalExtraNatives::GetBuiltinsCount())); 2785 2786 set_undefined_cell(*factory->NewCell(factory->undefined_value())); 2787 2788 // The symbol registry is initialized lazily. 2789 set_symbol_registry(Smi::FromInt(0)); 2790 2791 // Allocate object to hold object observation state. 2792 set_observation_state(*factory->NewJSObjectFromMap( 2793 factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize))); 2794 2795 // Microtask queue uses the empty fixed array as a sentinel for "empty". 2796 // Number of queued microtasks stored in Isolate::pending_microtask_count(). 2797 set_microtask_queue(empty_fixed_array()); 2798 2799 { 2800 StaticFeedbackVectorSpec spec; 2801 FeedbackVectorSlot load_ic_slot = spec.AddLoadICSlot(); 2802 FeedbackVectorSlot keyed_load_ic_slot = spec.AddKeyedLoadICSlot(); 2803 FeedbackVectorSlot store_ic_slot = spec.AddStoreICSlot(); 2804 FeedbackVectorSlot keyed_store_ic_slot = spec.AddKeyedStoreICSlot(); 2805 2806 DCHECK_EQ(load_ic_slot, 2807 FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)); 2808 DCHECK_EQ(keyed_load_ic_slot, 2809 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot)); 2810 DCHECK_EQ(store_ic_slot, 2811 FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)); 2812 DCHECK_EQ(keyed_store_ic_slot, 2813 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); 2814 2815 Handle<TypeFeedbackMetadata> dummy_metadata = 2816 TypeFeedbackMetadata::New(isolate(), &spec); 2817 Handle<TypeFeedbackVector> dummy_vector = 2818 TypeFeedbackVector::New(isolate(), dummy_metadata); 2819 2820 Object* megamorphic = *TypeFeedbackVector::MegamorphicSentinel(isolate()); 2821 dummy_vector->Set(load_ic_slot, megamorphic, SKIP_WRITE_BARRIER); 2822 dummy_vector->Set(keyed_load_ic_slot, megamorphic, SKIP_WRITE_BARRIER); 2823 dummy_vector->Set(store_ic_slot, megamorphic, SKIP_WRITE_BARRIER); 2824 dummy_vector->Set(keyed_store_ic_slot, megamorphic, SKIP_WRITE_BARRIER); 2825 2826 set_dummy_vector(*dummy_vector); 2827 } 2828 2829 { 2830 Handle<WeakCell> cell = factory->NewWeakCell(factory->undefined_value()); 2831 set_empty_weak_cell(*cell); 2832 cell->clear(); 2833 2834 Handle<FixedArray> cleared_optimized_code_map = 2835 factory->NewFixedArray(SharedFunctionInfo::kEntriesStart, TENURED); 2836 cleared_optimized_code_map->set(SharedFunctionInfo::kSharedCodeIndex, 2837 *cell); 2838 STATIC_ASSERT(SharedFunctionInfo::kEntriesStart == 1 && 2839 SharedFunctionInfo::kSharedCodeIndex == 0); 2840 set_cleared_optimized_code_map(*cleared_optimized_code_map); 2841 } 2842 2843 set_detached_contexts(empty_fixed_array()); 2844 set_retained_maps(ArrayList::cast(empty_fixed_array())); 2845 2846 set_weak_object_to_code_table( 2847 *WeakHashTable::New(isolate(), 16, USE_DEFAULT_MINIMUM_CAPACITY, 2848 TENURED)); 2849 2850 set_script_list(Smi::FromInt(0)); 2851 2852 Handle<SeededNumberDictionary> slow_element_dictionary = 2853 SeededNumberDictionary::New(isolate(), 0, TENURED); 2854 slow_element_dictionary->set_requires_slow_elements(); 2855 set_empty_slow_element_dictionary(*slow_element_dictionary); 2856 2857 set_materialized_objects(*factory->NewFixedArray(0, TENURED)); 2858 2859 // Handling of script id generation is in Heap::NextScriptId(). 2860 set_last_script_id(Smi::FromInt(v8::UnboundScript::kNoScriptId)); 2861 2862 // Allocate the empty script. 2863 Handle<Script> script = factory->NewScript(factory->empty_string()); 2864 script->set_type(Script::TYPE_NATIVE); 2865 set_empty_script(*script); 2866 2867 Handle<PropertyCell> cell = factory->NewPropertyCell(); 2868 cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid)); 2869 set_array_protector(*cell); 2870 2871 cell = factory->NewPropertyCell(); 2872 cell->set_value(the_hole_value()); 2873 set_empty_property_cell(*cell); 2874 2875 set_weak_stack_trace_list(Smi::FromInt(0)); 2876 2877 set_noscript_shared_function_infos(Smi::FromInt(0)); 2878 2879 // Will be filled in by Interpreter::Initialize(). 2880 set_interpreter_table( 2881 *interpreter::Interpreter::CreateUninitializedInterpreterTable( 2882 isolate())); 2883 2884 // Initialize keyed lookup cache. 2885 isolate_->keyed_lookup_cache()->Clear(); 2886 2887 // Initialize context slot cache. 2888 isolate_->context_slot_cache()->Clear(); 2889 2890 // Initialize descriptor cache. 2891 isolate_->descriptor_lookup_cache()->Clear(); 2892 2893 // Initialize compilation cache. 2894 isolate_->compilation_cache()->Clear(); 2895 } 2896 2897 2898 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { 2899 switch (root_index) { 2900 case kStoreBufferTopRootIndex: 2901 case kNumberStringCacheRootIndex: 2902 case kInstanceofCacheFunctionRootIndex: 2903 case kInstanceofCacheMapRootIndex: 2904 case kInstanceofCacheAnswerRootIndex: 2905 case kCodeStubsRootIndex: 2906 case kNonMonomorphicCacheRootIndex: 2907 case kPolymorphicCodeCacheRootIndex: 2908 case kEmptyScriptRootIndex: 2909 case kSymbolRegistryRootIndex: 2910 case kScriptListRootIndex: 2911 case kMaterializedObjectsRootIndex: 2912 case kMicrotaskQueueRootIndex: 2913 case kDetachedContextsRootIndex: 2914 case kWeakObjectToCodeTableRootIndex: 2915 case kRetainedMapsRootIndex: 2916 case kNoScriptSharedFunctionInfosRootIndex: 2917 case kWeakStackTraceListRootIndex: 2918 // Smi values 2919 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex: 2920 SMI_ROOT_LIST(SMI_ENTRY) 2921 #undef SMI_ENTRY 2922 // String table 2923 case kStringTableRootIndex: 2924 return true; 2925 2926 default: 2927 return false; 2928 } 2929 } 2930 2931 2932 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) { 2933 return !RootCanBeWrittenAfterInitialization(root_index) && 2934 !InNewSpace(root(root_index)); 2935 } 2936 2937 2938 int Heap::FullSizeNumberStringCacheLength() { 2939 // Compute the size of the number string cache based on the max newspace size. 2940 // The number string cache has a minimum size based on twice the initial cache 2941 // size to ensure that it is bigger after being made 'full size'. 2942 int number_string_cache_size = max_semi_space_size_ / 512; 2943 number_string_cache_size = Max(kInitialNumberStringCacheSize * 2, 2944 Min(0x4000, number_string_cache_size)); 2945 // There is a string and a number per entry so the length is twice the number 2946 // of entries. 2947 return number_string_cache_size * 2; 2948 } 2949 2950 2951 void Heap::FlushNumberStringCache() { 2952 // Flush the number to string cache. 2953 int len = number_string_cache()->length(); 2954 for (int i = 0; i < len; i++) { 2955 number_string_cache()->set_undefined(i); 2956 } 2957 } 2958 2959 2960 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) { 2961 return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]); 2962 } 2963 2964 2965 Heap::RootListIndex Heap::RootIndexForFixedTypedArray( 2966 ExternalArrayType array_type) { 2967 switch (array_type) { 2968 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ 2969 case kExternal##Type##Array: \ 2970 return kFixed##Type##ArrayMapRootIndex; 2971 2972 TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX) 2973 #undef ARRAY_TYPE_TO_ROOT_INDEX 2974 2975 default: 2976 UNREACHABLE(); 2977 return kUndefinedValueRootIndex; 2978 } 2979 } 2980 2981 2982 Heap::RootListIndex Heap::RootIndexForEmptyFixedTypedArray( 2983 ElementsKind elementsKind) { 2984 switch (elementsKind) { 2985 #define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ 2986 case TYPE##_ELEMENTS: \ 2987 return kEmptyFixed##Type##ArrayRootIndex; 2988 2989 TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX) 2990 #undef ELEMENT_KIND_TO_ROOT_INDEX 2991 default: 2992 UNREACHABLE(); 2993 return kUndefinedValueRootIndex; 2994 } 2995 } 2996 2997 2998 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) { 2999 return FixedTypedArrayBase::cast( 3000 roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]); 3001 } 3002 3003 3004 AllocationResult Heap::AllocateForeign(Address address, 3005 PretenureFlag pretenure) { 3006 // Statically ensure that it is safe to allocate foreigns in paged spaces. 3007 STATIC_ASSERT(Foreign::kSize <= Page::kMaxRegularHeapObjectSize); 3008 AllocationSpace space = (pretenure == TENURED) ? OLD_SPACE : NEW_SPACE; 3009 Foreign* result = nullptr; 3010 AllocationResult allocation = Allocate(foreign_map(), space); 3011 if (!allocation.To(&result)) return allocation; 3012 result->set_foreign_address(address); 3013 return result; 3014 } 3015 3016 3017 AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) { 3018 if (length < 0 || length > ByteArray::kMaxLength) { 3019 v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true); 3020 } 3021 int size = ByteArray::SizeFor(length); 3022 AllocationSpace space = SelectSpace(pretenure); 3023 HeapObject* result = nullptr; 3024 { 3025 AllocationResult allocation = AllocateRaw(size, space); 3026 if (!allocation.To(&result)) return allocation; 3027 } 3028 3029 result->set_map_no_write_barrier(byte_array_map()); 3030 ByteArray::cast(result)->set_length(length); 3031 return result; 3032 } 3033 3034 3035 AllocationResult Heap::AllocateBytecodeArray(int length, 3036 const byte* const raw_bytecodes, 3037 int frame_size, 3038 int parameter_count, 3039 FixedArray* constant_pool) { 3040 if (length < 0 || length > BytecodeArray::kMaxLength) { 3041 v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true); 3042 } 3043 // Bytecode array is pretenured, so constant pool array should be to. 3044 DCHECK(!InNewSpace(constant_pool)); 3045 3046 int size = BytecodeArray::SizeFor(length); 3047 HeapObject* result = nullptr; 3048 { 3049 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 3050 if (!allocation.To(&result)) return allocation; 3051 } 3052 3053 result->set_map_no_write_barrier(bytecode_array_map()); 3054 BytecodeArray* instance = BytecodeArray::cast(result); 3055 instance->set_length(length); 3056 instance->set_frame_size(frame_size); 3057 instance->set_parameter_count(parameter_count); 3058 instance->set_constant_pool(constant_pool); 3059 CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); 3060 3061 return result; 3062 } 3063 3064 3065 void Heap::CreateFillerObjectAt(Address addr, int size) { 3066 if (size == 0) return; 3067 HeapObject* filler = HeapObject::FromAddress(addr); 3068 if (size == kPointerSize) { 3069 filler->set_map_no_write_barrier( 3070 reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex))); 3071 } else if (size == 2 * kPointerSize) { 3072 filler->set_map_no_write_barrier( 3073 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); 3074 } else { 3075 DCHECK_GT(size, 2 * kPointerSize); 3076 filler->set_map_no_write_barrier( 3077 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); 3078 FreeSpace::cast(filler)->nobarrier_set_size(size); 3079 } 3080 // At this point, we may be deserializing the heap from a snapshot, and 3081 // none of the maps have been created yet and are NULL. 3082 DCHECK((filler->map() == NULL && !deserialization_complete_) || 3083 filler->map()->IsMap()); 3084 } 3085 3086 3087 bool Heap::CanMoveObjectStart(HeapObject* object) { 3088 if (!FLAG_move_object_start) return false; 3089 3090 Address address = object->address(); 3091 3092 if (lo_space()->Contains(object)) return false; 3093 3094 Page* page = Page::FromAddress(address); 3095 // We can move the object start if: 3096 // (1) the object is not in old space, 3097 // (2) the page of the object was already swept, 3098 // (3) the page was already concurrently swept. This case is an optimization 3099 // for concurrent sweeping. The WasSwept predicate for concurrently swept 3100 // pages is set after sweeping all pages. 3101 return !InOldSpace(address) || page->WasSwept() || page->SweepingCompleted(); 3102 } 3103 3104 3105 void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) { 3106 // As long as the inspected object is black and we are currently not iterating 3107 // the heap using HeapIterator, we can update the live byte count. We cannot 3108 // update while using HeapIterator because the iterator is temporarily 3109 // marking the whole object graph, without updating live bytes. 3110 if (!in_heap_iterator() && 3111 !mark_compact_collector()->sweeping_in_progress() && 3112 Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { 3113 if (mode == SEQUENTIAL_TO_SWEEPER) { 3114 MemoryChunk::IncrementLiveBytesFromGC(object, by); 3115 } else { 3116 MemoryChunk::IncrementLiveBytesFromMutator(object, by); 3117 } 3118 } 3119 } 3120 3121 3122 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object, 3123 int elements_to_trim) { 3124 DCHECK(!object->IsFixedTypedArrayBase()); 3125 DCHECK(!object->IsByteArray()); 3126 const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize; 3127 const int bytes_to_trim = elements_to_trim * element_size; 3128 Map* map = object->map(); 3129 3130 // For now this trick is only applied to objects in new and paged space. 3131 // In large object space the object's start must coincide with chunk 3132 // and thus the trick is just not applicable. 3133 DCHECK(!lo_space()->Contains(object)); 3134 DCHECK(object->map() != fixed_cow_array_map()); 3135 3136 STATIC_ASSERT(FixedArrayBase::kMapOffset == 0); 3137 STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize); 3138 STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize); 3139 3140 const int len = object->length(); 3141 DCHECK(elements_to_trim <= len); 3142 3143 // Calculate location of new array start. 3144 Address new_start = object->address() + bytes_to_trim; 3145 3146 // Technically in new space this write might be omitted (except for 3147 // debug mode which iterates through the heap), but to play safer 3148 // we still do it. 3149 CreateFillerObjectAt(object->address(), bytes_to_trim); 3150 3151 // Initialize header of the trimmed array. Since left trimming is only 3152 // performed on pages which are not concurrently swept creating a filler 3153 // object does not require synchronization. 3154 DCHECK(CanMoveObjectStart(object)); 3155 Object** former_start = HeapObject::RawField(object, 0); 3156 int new_start_index = elements_to_trim * (element_size / kPointerSize); 3157 former_start[new_start_index] = map; 3158 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); 3159 FixedArrayBase* new_object = 3160 FixedArrayBase::cast(HeapObject::FromAddress(new_start)); 3161 3162 // Maintain consistency of live bytes during incremental marking 3163 Marking::TransferMark(this, object->address(), new_start); 3164 AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER); 3165 3166 // Notify the heap profiler of change in object layout. 3167 OnMoveEvent(new_object, object, new_object->Size()); 3168 return new_object; 3169 } 3170 3171 3172 // Force instantiation of templatized method. 3173 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>( 3174 FixedArrayBase*, int); 3175 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( 3176 FixedArrayBase*, int); 3177 3178 3179 template<Heap::InvocationMode mode> 3180 void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) { 3181 const int len = object->length(); 3182 DCHECK_LE(elements_to_trim, len); 3183 DCHECK_GE(elements_to_trim, 0); 3184 3185 int bytes_to_trim; 3186 if (object->IsFixedTypedArrayBase()) { 3187 InstanceType type = object->map()->instance_type(); 3188 bytes_to_trim = 3189 FixedTypedArrayBase::TypedArraySize(type, len) - 3190 FixedTypedArrayBase::TypedArraySize(type, len - elements_to_trim); 3191 } else if (object->IsByteArray()) { 3192 int new_size = ByteArray::SizeFor(len - elements_to_trim); 3193 bytes_to_trim = ByteArray::SizeFor(len) - new_size; 3194 DCHECK_GE(bytes_to_trim, 0); 3195 } else { 3196 const int element_size = 3197 object->IsFixedArray() ? kPointerSize : kDoubleSize; 3198 bytes_to_trim = elements_to_trim * element_size; 3199 } 3200 3201 3202 // For now this trick is only applied to objects in new and paged space. 3203 DCHECK(object->map() != fixed_cow_array_map()); 3204 3205 if (bytes_to_trim == 0) { 3206 // No need to create filler and update live bytes counters, just initialize 3207 // header of the trimmed array. 3208 object->synchronized_set_length(len - elements_to_trim); 3209 return; 3210 } 3211 3212 // Calculate location of new array end. 3213 Address new_end = object->address() + object->Size() - bytes_to_trim; 3214 3215 // Technically in new space this write might be omitted (except for 3216 // debug mode which iterates through the heap), but to play safer 3217 // we still do it. 3218 // We do not create a filler for objects in large object space. 3219 // TODO(hpayer): We should shrink the large object page if the size 3220 // of the object changed significantly. 3221 if (!lo_space()->Contains(object)) { 3222 CreateFillerObjectAt(new_end, bytes_to_trim); 3223 } 3224 3225 // Initialize header of the trimmed array. We are storing the new length 3226 // using release store after creating a filler for the left-over space to 3227 // avoid races with the sweeper thread. 3228 object->synchronized_set_length(len - elements_to_trim); 3229 3230 // Maintain consistency of live bytes during incremental marking 3231 AdjustLiveBytes(object, -bytes_to_trim, mode); 3232 3233 // Notify the heap profiler of change in object layout. The array may not be 3234 // moved during GC, and size has to be adjusted nevertheless. 3235 HeapProfiler* profiler = isolate()->heap_profiler(); 3236 if (profiler->is_tracking_allocations()) { 3237 profiler->UpdateObjectSizeEvent(object->address(), object->Size()); 3238 } 3239 } 3240 3241 3242 AllocationResult Heap::AllocateFixedTypedArrayWithExternalPointer( 3243 int length, ExternalArrayType array_type, void* external_pointer, 3244 PretenureFlag pretenure) { 3245 int size = FixedTypedArrayBase::kHeaderSize; 3246 AllocationSpace space = SelectSpace(pretenure); 3247 HeapObject* result = nullptr; 3248 { 3249 AllocationResult allocation = AllocateRaw(size, space); 3250 if (!allocation.To(&result)) return allocation; 3251 } 3252 3253 result->set_map_no_write_barrier(MapForFixedTypedArray(array_type)); 3254 FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(result); 3255 elements->set_base_pointer(Smi::FromInt(0), SKIP_WRITE_BARRIER); 3256 elements->set_external_pointer(external_pointer, SKIP_WRITE_BARRIER); 3257 elements->set_length(length); 3258 return elements; 3259 } 3260 3261 static void ForFixedTypedArray(ExternalArrayType array_type, int* element_size, 3262 ElementsKind* element_kind) { 3263 switch (array_type) { 3264 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 3265 case kExternal##Type##Array: \ 3266 *element_size = size; \ 3267 *element_kind = TYPE##_ELEMENTS; \ 3268 return; 3269 3270 TYPED_ARRAYS(TYPED_ARRAY_CASE) 3271 #undef TYPED_ARRAY_CASE 3272 3273 default: 3274 *element_size = 0; // Bogus 3275 *element_kind = UINT8_ELEMENTS; // Bogus 3276 UNREACHABLE(); 3277 } 3278 } 3279 3280 3281 AllocationResult Heap::AllocateFixedTypedArray(int length, 3282 ExternalArrayType array_type, 3283 bool initialize, 3284 PretenureFlag pretenure) { 3285 int element_size; 3286 ElementsKind elements_kind; 3287 ForFixedTypedArray(array_type, &element_size, &elements_kind); 3288 int size = OBJECT_POINTER_ALIGN(length * element_size + 3289 FixedTypedArrayBase::kDataOffset); 3290 AllocationSpace space = SelectSpace(pretenure); 3291 3292 HeapObject* object = nullptr; 3293 AllocationResult allocation = AllocateRaw( 3294 size, space, 3295 array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned); 3296 if (!allocation.To(&object)) return allocation; 3297 3298 object->set_map_no_write_barrier(MapForFixedTypedArray(array_type)); 3299 FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object); 3300 elements->set_base_pointer(elements, SKIP_WRITE_BARRIER); 3301 elements->set_external_pointer( 3302 ExternalReference::fixed_typed_array_base_data_offset().address(), 3303 SKIP_WRITE_BARRIER); 3304 elements->set_length(length); 3305 if (initialize) memset(elements->DataPtr(), 0, elements->DataSize()); 3306 return elements; 3307 } 3308 3309 3310 AllocationResult Heap::AllocateCode(int object_size, bool immovable) { 3311 DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment)); 3312 AllocationResult allocation = AllocateRaw(object_size, CODE_SPACE); 3313 3314 HeapObject* result = nullptr; 3315 if (!allocation.To(&result)) return allocation; 3316 3317 if (immovable) { 3318 Address address = result->address(); 3319 // Code objects which should stay at a fixed address are allocated either 3320 // in the first page of code space (objects on the first page of each space 3321 // are never moved) or in large object space. 3322 if (!code_space_->FirstPage()->Contains(address) && 3323 MemoryChunk::FromAddress(address)->owner()->identity() != LO_SPACE) { 3324 // Discard the first code allocation, which was on a page where it could 3325 // be moved. 3326 CreateFillerObjectAt(result->address(), object_size); 3327 allocation = lo_space_->AllocateRaw(object_size, EXECUTABLE); 3328 if (!allocation.To(&result)) return allocation; 3329 OnAllocationEvent(result, object_size); 3330 } 3331 } 3332 3333 result->set_map_no_write_barrier(code_map()); 3334 Code* code = Code::cast(result); 3335 DCHECK(IsAligned(bit_cast<intptr_t>(code->address()), kCodeAlignment)); 3336 DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() || 3337 isolate_->code_range()->contains(code->address()) || 3338 object_size <= code_space()->AreaSize()); 3339 code->set_gc_metadata(Smi::FromInt(0)); 3340 code->set_ic_age(global_ic_age_); 3341 return code; 3342 } 3343 3344 3345 AllocationResult Heap::CopyCode(Code* code) { 3346 AllocationResult allocation; 3347 3348 HeapObject* result = nullptr; 3349 // Allocate an object the same size as the code object. 3350 int obj_size = code->Size(); 3351 allocation = AllocateRaw(obj_size, CODE_SPACE); 3352 if (!allocation.To(&result)) return allocation; 3353 3354 // Copy code object. 3355 Address old_addr = code->address(); 3356 Address new_addr = result->address(); 3357 CopyBlock(new_addr, old_addr, obj_size); 3358 Code* new_code = Code::cast(result); 3359 3360 // Relocate the copy. 3361 DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment)); 3362 DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() || 3363 isolate_->code_range()->contains(code->address()) || 3364 obj_size <= code_space()->AreaSize()); 3365 new_code->Relocate(new_addr - old_addr); 3366 return new_code; 3367 } 3368 3369 3370 AllocationResult Heap::CopyCode(Code* code, Vector<byte> reloc_info) { 3371 // Allocate ByteArray before the Code object, so that we do not risk 3372 // leaving uninitialized Code object (and breaking the heap). 3373 ByteArray* reloc_info_array = nullptr; 3374 { 3375 AllocationResult allocation = 3376 AllocateByteArray(reloc_info.length(), TENURED); 3377 if (!allocation.To(&reloc_info_array)) return allocation; 3378 } 3379 3380 int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment); 3381 3382 int new_obj_size = Code::SizeFor(new_body_size); 3383 3384 Address old_addr = code->address(); 3385 3386 size_t relocation_offset = 3387 static_cast<size_t>(code->instruction_end() - old_addr); 3388 3389 HeapObject* result = nullptr; 3390 AllocationResult allocation = AllocateRaw(new_obj_size, CODE_SPACE); 3391 if (!allocation.To(&result)) return allocation; 3392 3393 // Copy code object. 3394 Address new_addr = result->address(); 3395 3396 // Copy header and instructions. 3397 CopyBytes(new_addr, old_addr, relocation_offset); 3398 3399 Code* new_code = Code::cast(result); 3400 new_code->set_relocation_info(reloc_info_array); 3401 3402 // Copy patched rinfo. 3403 CopyBytes(new_code->relocation_start(), reloc_info.start(), 3404 static_cast<size_t>(reloc_info.length())); 3405 3406 // Relocate the copy. 3407 DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment)); 3408 DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() || 3409 isolate_->code_range()->contains(code->address()) || 3410 new_obj_size <= code_space()->AreaSize()); 3411 3412 new_code->Relocate(new_addr - old_addr); 3413 3414 #ifdef VERIFY_HEAP 3415 if (FLAG_verify_heap) code->ObjectVerify(); 3416 #endif 3417 return new_code; 3418 } 3419 3420 3421 void Heap::InitializeAllocationMemento(AllocationMemento* memento, 3422 AllocationSite* allocation_site) { 3423 memento->set_map_no_write_barrier(allocation_memento_map()); 3424 DCHECK(allocation_site->map() == allocation_site_map()); 3425 memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER); 3426 if (FLAG_allocation_site_pretenuring) { 3427 allocation_site->IncrementMementoCreateCount(); 3428 } 3429 } 3430 3431 3432 AllocationResult Heap::Allocate(Map* map, AllocationSpace space, 3433 AllocationSite* allocation_site) { 3434 DCHECK(gc_state_ == NOT_IN_GC); 3435 DCHECK(map->instance_type() != MAP_TYPE); 3436 int size = map->instance_size(); 3437 if (allocation_site != NULL) { 3438 size += AllocationMemento::kSize; 3439 } 3440 HeapObject* result = nullptr; 3441 AllocationResult allocation = AllocateRaw(size, space); 3442 if (!allocation.To(&result)) return allocation; 3443 // No need for write barrier since object is white and map is in old space. 3444 result->set_map_no_write_barrier(map); 3445 if (allocation_site != NULL) { 3446 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( 3447 reinterpret_cast<Address>(result) + map->instance_size()); 3448 InitializeAllocationMemento(alloc_memento, allocation_site); 3449 } 3450 return result; 3451 } 3452 3453 3454 void Heap::InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties, 3455 Map* map) { 3456 obj->set_properties(properties); 3457 obj->initialize_elements(); 3458 // TODO(1240798): Initialize the object's body using valid initial values 3459 // according to the object's initial map. For example, if the map's 3460 // instance type is JS_ARRAY_TYPE, the length field should be initialized 3461 // to a number (e.g. Smi::FromInt(0)) and the elements initialized to a 3462 // fixed array (e.g. Heap::empty_fixed_array()). Currently, the object 3463 // verification code has to cope with (temporarily) invalid objects. See 3464 // for example, JSArray::JSArrayVerify). 3465 InitializeJSObjectBody(obj, map, JSObject::kHeaderSize); 3466 } 3467 3468 3469 void Heap::InitializeJSObjectBody(JSObject* obj, Map* map, int start_offset) { 3470 if (start_offset == map->instance_size()) return; 3471 DCHECK_LT(start_offset, map->instance_size()); 3472 3473 Object* filler; 3474 // We cannot always fill with one_pointer_filler_map because objects 3475 // created from API functions expect their internal fields to be initialized 3476 // with undefined_value. 3477 // Pre-allocated fields need to be initialized with undefined_value as well 3478 // so that object accesses before the constructor completes (e.g. in the 3479 // debugger) will not cause a crash. 3480 3481 // In case of Array subclassing the |map| could already be transitioned 3482 // to different elements kind from the initial map on which we track slack. 3483 Map* initial_map = map->FindRootMap(); 3484 if (initial_map->IsInobjectSlackTrackingInProgress()) { 3485 // We might want to shrink the object later. 3486 filler = Heap::one_pointer_filler_map(); 3487 } else { 3488 filler = Heap::undefined_value(); 3489 } 3490 obj->InitializeBody(map, start_offset, Heap::undefined_value(), filler); 3491 initial_map->InobjectSlackTrackingStep(); 3492 } 3493 3494 3495 AllocationResult Heap::AllocateJSObjectFromMap( 3496 Map* map, PretenureFlag pretenure, AllocationSite* allocation_site) { 3497 // JSFunctions should be allocated using AllocateFunction to be 3498 // properly initialized. 3499 DCHECK(map->instance_type() != JS_FUNCTION_TYPE); 3500 3501 // Both types of global objects should be allocated using 3502 // AllocateGlobalObject to be properly initialized. 3503 DCHECK(map->instance_type() != JS_GLOBAL_OBJECT_TYPE); 3504 3505 // Allocate the backing storage for the properties. 3506 FixedArray* properties = empty_fixed_array(); 3507 3508 // Allocate the JSObject. 3509 AllocationSpace space = SelectSpace(pretenure); 3510 JSObject* js_obj = nullptr; 3511 AllocationResult allocation = Allocate(map, space, allocation_site); 3512 if (!allocation.To(&js_obj)) return allocation; 3513 3514 // Initialize the JSObject. 3515 InitializeJSObjectFromMap(js_obj, properties, map); 3516 DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements()); 3517 return js_obj; 3518 } 3519 3520 3521 AllocationResult Heap::AllocateJSObject(JSFunction* constructor, 3522 PretenureFlag pretenure, 3523 AllocationSite* allocation_site) { 3524 DCHECK(constructor->has_initial_map()); 3525 3526 // Allocate the object based on the constructors initial map. 3527 AllocationResult allocation = AllocateJSObjectFromMap( 3528 constructor->initial_map(), pretenure, allocation_site); 3529 #ifdef DEBUG 3530 // Make sure result is NOT a global object if valid. 3531 HeapObject* obj = nullptr; 3532 DCHECK(!allocation.To(&obj) || !obj->IsJSGlobalObject()); 3533 #endif 3534 return allocation; 3535 } 3536 3537 3538 AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) { 3539 // Make the clone. 3540 Map* map = source->map(); 3541 3542 // We can only clone regexps, normal objects or arrays. Copying anything else 3543 // will break invariants. 3544 CHECK(map->instance_type() == JS_REGEXP_TYPE || 3545 map->instance_type() == JS_OBJECT_TYPE || 3546 map->instance_type() == JS_ARRAY_TYPE); 3547 3548 int object_size = map->instance_size(); 3549 HeapObject* clone = nullptr; 3550 3551 DCHECK(site == NULL || AllocationSite::CanTrack(map->instance_type())); 3552 3553 int adjusted_object_size = 3554 site != NULL ? object_size + AllocationMemento::kSize : object_size; 3555 AllocationResult allocation = AllocateRaw(adjusted_object_size, NEW_SPACE); 3556 if (!allocation.To(&clone)) return allocation; 3557 3558 SLOW_DCHECK(InNewSpace(clone)); 3559 // Since we know the clone is allocated in new space, we can copy 3560 // the contents without worrying about updating the write barrier. 3561 CopyBlock(clone->address(), source->address(), object_size); 3562 3563 if (site != NULL) { 3564 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( 3565 reinterpret_cast<Address>(clone) + object_size); 3566 InitializeAllocationMemento(alloc_memento, site); 3567 } 3568 3569 SLOW_DCHECK(JSObject::cast(clone)->GetElementsKind() == 3570 source->GetElementsKind()); 3571 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); 3572 FixedArray* properties = FixedArray::cast(source->properties()); 3573 // Update elements if necessary. 3574 if (elements->length() > 0) { 3575 FixedArrayBase* elem = nullptr; 3576 { 3577 AllocationResult allocation; 3578 if (elements->map() == fixed_cow_array_map()) { 3579 allocation = FixedArray::cast(elements); 3580 } else if (source->HasFastDoubleElements()) { 3581 allocation = CopyFixedDoubleArray(FixedDoubleArray::cast(elements)); 3582 } else { 3583 allocation = CopyFixedArray(FixedArray::cast(elements)); 3584 } 3585 if (!allocation.To(&elem)) return allocation; 3586 } 3587 JSObject::cast(clone)->set_elements(elem, SKIP_WRITE_BARRIER); 3588 } 3589 // Update properties if necessary. 3590 if (properties->length() > 0) { 3591 FixedArray* prop = nullptr; 3592 { 3593 AllocationResult allocation = CopyFixedArray(properties); 3594 if (!allocation.To(&prop)) return allocation; 3595 } 3596 JSObject::cast(clone)->set_properties(prop, SKIP_WRITE_BARRIER); 3597 } 3598 // Return the new clone. 3599 return clone; 3600 } 3601 3602 3603 static inline void WriteOneByteData(Vector<const char> vector, uint8_t* chars, 3604 int len) { 3605 // Only works for one byte strings. 3606 DCHECK(vector.length() == len); 3607 MemCopy(chars, vector.start(), len); 3608 } 3609 3610 static inline void WriteTwoByteData(Vector<const char> vector, uint16_t* chars, 3611 int len) { 3612 const uint8_t* stream = reinterpret_cast<const uint8_t*>(vector.start()); 3613 size_t stream_length = vector.length(); 3614 while (stream_length != 0) { 3615 size_t consumed = 0; 3616 uint32_t c = unibrow::Utf8::ValueOf(stream, stream_length, &consumed); 3617 DCHECK(c != unibrow::Utf8::kBadChar); 3618 DCHECK(consumed <= stream_length); 3619 stream_length -= consumed; 3620 stream += consumed; 3621 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) { 3622 len -= 2; 3623 if (len < 0) break; 3624 *chars++ = unibrow::Utf16::LeadSurrogate(c); 3625 *chars++ = unibrow::Utf16::TrailSurrogate(c); 3626 } else { 3627 len -= 1; 3628 if (len < 0) break; 3629 *chars++ = c; 3630 } 3631 } 3632 DCHECK(stream_length == 0); 3633 DCHECK(len == 0); 3634 } 3635 3636 3637 static inline void WriteOneByteData(String* s, uint8_t* chars, int len) { 3638 DCHECK(s->length() == len); 3639 String::WriteToFlat(s, chars, 0, len); 3640 } 3641 3642 3643 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) { 3644 DCHECK(s->length() == len); 3645 String::WriteToFlat(s, chars, 0, len); 3646 } 3647 3648 3649 template <bool is_one_byte, typename T> 3650 AllocationResult Heap::AllocateInternalizedStringImpl(T t, int chars, 3651 uint32_t hash_field) { 3652 DCHECK(chars >= 0); 3653 // Compute map and object size. 3654 int size; 3655 Map* map; 3656 3657 DCHECK_LE(0, chars); 3658 DCHECK_GE(String::kMaxLength, chars); 3659 if (is_one_byte) { 3660 map = one_byte_internalized_string_map(); 3661 size = SeqOneByteString::SizeFor(chars); 3662 } else { 3663 map = internalized_string_map(); 3664 size = SeqTwoByteString::SizeFor(chars); 3665 } 3666 3667 // Allocate string. 3668 HeapObject* result = nullptr; 3669 { 3670 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 3671 if (!allocation.To(&result)) return allocation; 3672 } 3673 3674 result->set_map_no_write_barrier(map); 3675 // Set length and hash fields of the allocated string. 3676 String* answer = String::cast(result); 3677 answer->set_length(chars); 3678 answer->set_hash_field(hash_field); 3679 3680 DCHECK_EQ(size, answer->Size()); 3681 3682 if (is_one_byte) { 3683 WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars); 3684 } else { 3685 WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars); 3686 } 3687 return answer; 3688 } 3689 3690 3691 // Need explicit instantiations. 3692 template AllocationResult Heap::AllocateInternalizedStringImpl<true>(String*, 3693 int, 3694 uint32_t); 3695 template AllocationResult Heap::AllocateInternalizedStringImpl<false>(String*, 3696 int, 3697 uint32_t); 3698 template AllocationResult Heap::AllocateInternalizedStringImpl<false>( 3699 Vector<const char>, int, uint32_t); 3700 3701 3702 AllocationResult Heap::AllocateRawOneByteString(int length, 3703 PretenureFlag pretenure) { 3704 DCHECK_LE(0, length); 3705 DCHECK_GE(String::kMaxLength, length); 3706 int size = SeqOneByteString::SizeFor(length); 3707 DCHECK(size <= SeqOneByteString::kMaxSize); 3708 AllocationSpace space = SelectSpace(pretenure); 3709 3710 HeapObject* result = nullptr; 3711 { 3712 AllocationResult allocation = AllocateRaw(size, space); 3713 if (!allocation.To(&result)) return allocation; 3714 } 3715 3716 // Partially initialize the object. 3717 result->set_map_no_write_barrier(one_byte_string_map()); 3718 String::cast(result)->set_length(length); 3719 String::cast(result)->set_hash_field(String::kEmptyHashField); 3720 DCHECK_EQ(size, HeapObject::cast(result)->Size()); 3721 3722 return result; 3723 } 3724 3725 3726 AllocationResult Heap::AllocateRawTwoByteString(int length, 3727 PretenureFlag pretenure) { 3728 DCHECK_LE(0, length); 3729 DCHECK_GE(String::kMaxLength, length); 3730 int size = SeqTwoByteString::SizeFor(length); 3731 DCHECK(size <= SeqTwoByteString::kMaxSize); 3732 AllocationSpace space = SelectSpace(pretenure); 3733 3734 HeapObject* result = nullptr; 3735 { 3736 AllocationResult allocation = AllocateRaw(size, space); 3737 if (!allocation.To(&result)) return allocation; 3738 } 3739 3740 // Partially initialize the object. 3741 result->set_map_no_write_barrier(string_map()); 3742 String::cast(result)->set_length(length); 3743 String::cast(result)->set_hash_field(String::kEmptyHashField); 3744 DCHECK_EQ(size, HeapObject::cast(result)->Size()); 3745 return result; 3746 } 3747 3748 3749 AllocationResult Heap::AllocateEmptyFixedArray() { 3750 int size = FixedArray::SizeFor(0); 3751 HeapObject* result = nullptr; 3752 { 3753 AllocationResult allocation = AllocateRaw(size, OLD_SPACE); 3754 if (!allocation.To(&result)) return allocation; 3755 } 3756 // Initialize the object. 3757 result->set_map_no_write_barrier(fixed_array_map()); 3758 FixedArray::cast(result)->set_length(0); 3759 return result; 3760 } 3761 3762 3763 AllocationResult Heap::CopyAndTenureFixedCOWArray(FixedArray* src) { 3764 if (!InNewSpace(src)) { 3765 return src; 3766 } 3767 3768 int len = src->length(); 3769 HeapObject* obj = nullptr; 3770 { 3771 AllocationResult allocation = AllocateRawFixedArray(len, TENURED); 3772 if (!allocation.To(&obj)) return allocation; 3773 } 3774 obj->set_map_no_write_barrier(fixed_array_map()); 3775 FixedArray* result = FixedArray::cast(obj); 3776 result->set_length(len); 3777 3778 // Copy the content. 3779 DisallowHeapAllocation no_gc; 3780 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 3781 for (int i = 0; i < len; i++) result->set(i, src->get(i), mode); 3782 3783 // TODO(mvstanton): The map is set twice because of protection against calling 3784 // set() on a COW FixedArray. Issue v8:3221 created to track this, and 3785 // we might then be able to remove this whole method. 3786 HeapObject::cast(obj)->set_map_no_write_barrier(fixed_cow_array_map()); 3787 return result; 3788 } 3789 3790 3791 AllocationResult Heap::AllocateEmptyFixedTypedArray( 3792 ExternalArrayType array_type) { 3793 return AllocateFixedTypedArray(0, array_type, false, TENURED); 3794 } 3795 3796 3797 AllocationResult Heap::CopyFixedArrayAndGrow(FixedArray* src, int grow_by, 3798 PretenureFlag pretenure) { 3799 int old_len = src->length(); 3800 int new_len = old_len + grow_by; 3801 DCHECK(new_len >= old_len); 3802 HeapObject* obj = nullptr; 3803 { 3804 AllocationResult allocation = AllocateRawFixedArray(new_len, pretenure); 3805 if (!allocation.To(&obj)) return allocation; 3806 } 3807 obj->set_map_no_write_barrier(fixed_array_map()); 3808 FixedArray* result = FixedArray::cast(obj); 3809 result->set_length(new_len); 3810 3811 // Copy the content. 3812 DisallowHeapAllocation no_gc; 3813 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 3814 for (int i = 0; i < old_len; i++) result->set(i, src->get(i), mode); 3815 MemsetPointer(result->data_start() + old_len, undefined_value(), grow_by); 3816 return result; 3817 } 3818 3819 3820 AllocationResult Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { 3821 int len = src->length(); 3822 HeapObject* obj = nullptr; 3823 { 3824 AllocationResult allocation = AllocateRawFixedArray(len, NOT_TENURED); 3825 if (!allocation.To(&obj)) return allocation; 3826 } 3827 if (InNewSpace(obj)) { 3828 obj->set_map_no_write_barrier(map); 3829 CopyBlock(obj->address() + kPointerSize, src->address() + kPointerSize, 3830 FixedArray::SizeFor(len) - kPointerSize); 3831 return obj; 3832 } 3833 obj->set_map_no_write_barrier(map); 3834 FixedArray* result = FixedArray::cast(obj); 3835 result->set_length(len); 3836 3837 // Copy the content. 3838 DisallowHeapAllocation no_gc; 3839 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 3840 for (int i = 0; i < len; i++) result->set(i, src->get(i), mode); 3841 return result; 3842 } 3843 3844 3845 AllocationResult Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src, 3846 Map* map) { 3847 int len = src->length(); 3848 HeapObject* obj = nullptr; 3849 { 3850 AllocationResult allocation = AllocateRawFixedDoubleArray(len, NOT_TENURED); 3851 if (!allocation.To(&obj)) return allocation; 3852 } 3853 obj->set_map_no_write_barrier(map); 3854 CopyBlock(obj->address() + FixedDoubleArray::kLengthOffset, 3855 src->address() + FixedDoubleArray::kLengthOffset, 3856 FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset); 3857 return obj; 3858 } 3859 3860 3861 AllocationResult Heap::AllocateRawFixedArray(int length, 3862 PretenureFlag pretenure) { 3863 if (length < 0 || length > FixedArray::kMaxLength) { 3864 v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true); 3865 } 3866 int size = FixedArray::SizeFor(length); 3867 AllocationSpace space = SelectSpace(pretenure); 3868 3869 return AllocateRaw(size, space); 3870 } 3871 3872 3873 AllocationResult Heap::AllocateFixedArrayWithFiller(int length, 3874 PretenureFlag pretenure, 3875 Object* filler) { 3876 DCHECK(length >= 0); 3877 DCHECK(empty_fixed_array()->IsFixedArray()); 3878 if (length == 0) return empty_fixed_array(); 3879 3880 DCHECK(!InNewSpace(filler)); 3881 HeapObject* result = nullptr; 3882 { 3883 AllocationResult allocation = AllocateRawFixedArray(length, pretenure); 3884 if (!allocation.To(&result)) return allocation; 3885 } 3886 3887 result->set_map_no_write_barrier(fixed_array_map()); 3888 FixedArray* array = FixedArray::cast(result); 3889 array->set_length(length); 3890 MemsetPointer(array->data_start(), filler, length); 3891 return array; 3892 } 3893 3894 3895 AllocationResult Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { 3896 return AllocateFixedArrayWithFiller(length, pretenure, undefined_value()); 3897 } 3898 3899 3900 AllocationResult Heap::AllocateUninitializedFixedArray(int length) { 3901 if (length == 0) return empty_fixed_array(); 3902 3903 HeapObject* obj = nullptr; 3904 { 3905 AllocationResult allocation = AllocateRawFixedArray(length, NOT_TENURED); 3906 if (!allocation.To(&obj)) return allocation; 3907 } 3908 3909 obj->set_map_no_write_barrier(fixed_array_map()); 3910 FixedArray::cast(obj)->set_length(length); 3911 return obj; 3912 } 3913 3914 3915 AllocationResult Heap::AllocateUninitializedFixedDoubleArray( 3916 int length, PretenureFlag pretenure) { 3917 if (length == 0) return empty_fixed_array(); 3918 3919 HeapObject* elements = nullptr; 3920 AllocationResult allocation = AllocateRawFixedDoubleArray(length, pretenure); 3921 if (!allocation.To(&elements)) return allocation; 3922 3923 elements->set_map_no_write_barrier(fixed_double_array_map()); 3924 FixedDoubleArray::cast(elements)->set_length(length); 3925 return elements; 3926 } 3927 3928 3929 AllocationResult Heap::AllocateRawFixedDoubleArray(int length, 3930 PretenureFlag pretenure) { 3931 if (length < 0 || length > FixedDoubleArray::kMaxLength) { 3932 v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", 3933 kDoubleAligned); 3934 } 3935 int size = FixedDoubleArray::SizeFor(length); 3936 AllocationSpace space = SelectSpace(pretenure); 3937 3938 HeapObject* object = nullptr; 3939 { 3940 AllocationResult allocation = AllocateRaw(size, space, kDoubleAligned); 3941 if (!allocation.To(&object)) return allocation; 3942 } 3943 3944 return object; 3945 } 3946 3947 3948 AllocationResult Heap::AllocateSymbol() { 3949 // Statically ensure that it is safe to allocate symbols in paged spaces. 3950 STATIC_ASSERT(Symbol::kSize <= Page::kMaxRegularHeapObjectSize); 3951 3952 HeapObject* result = nullptr; 3953 AllocationResult allocation = AllocateRaw(Symbol::kSize, OLD_SPACE); 3954 if (!allocation.To(&result)) return allocation; 3955 3956 result->set_map_no_write_barrier(symbol_map()); 3957 3958 // Generate a random hash value. 3959 int hash; 3960 int attempts = 0; 3961 do { 3962 hash = isolate()->random_number_generator()->NextInt() & Name::kHashBitMask; 3963 attempts++; 3964 } while (hash == 0 && attempts < 30); 3965 if (hash == 0) hash = 1; // never return 0 3966 3967 Symbol::cast(result) 3968 ->set_hash_field(Name::kIsNotArrayIndexMask | (hash << Name::kHashShift)); 3969 Symbol::cast(result)->set_name(undefined_value()); 3970 Symbol::cast(result)->set_flags(0); 3971 3972 DCHECK(!Symbol::cast(result)->is_private()); 3973 return result; 3974 } 3975 3976 3977 AllocationResult Heap::AllocateStruct(InstanceType type) { 3978 Map* map; 3979 switch (type) { 3980 #define MAKE_CASE(NAME, Name, name) \ 3981 case NAME##_TYPE: \ 3982 map = name##_map(); \ 3983 break; 3984 STRUCT_LIST(MAKE_CASE) 3985 #undef MAKE_CASE 3986 default: 3987 UNREACHABLE(); 3988 return exception(); 3989 } 3990 int size = map->instance_size(); 3991 Struct* result = nullptr; 3992 { 3993 AllocationResult allocation = Allocate(map, OLD_SPACE); 3994 if (!allocation.To(&result)) return allocation; 3995 } 3996 result->InitializeBody(size); 3997 return result; 3998 } 3999 4000 4001 bool Heap::IsHeapIterable() { 4002 // TODO(hpayer): This function is not correct. Allocation folding in old 4003 // space breaks the iterability. 4004 return new_space_top_after_last_gc_ == new_space()->top(); 4005 } 4006 4007 4008 void Heap::MakeHeapIterable() { 4009 DCHECK(AllowHeapAllocation::IsAllowed()); 4010 if (!IsHeapIterable()) { 4011 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); 4012 } 4013 if (mark_compact_collector()->sweeping_in_progress()) { 4014 mark_compact_collector()->EnsureSweepingCompleted(); 4015 } 4016 DCHECK(IsHeapIterable()); 4017 } 4018 4019 4020 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { 4021 const double kMinMutatorUtilization = 0.0; 4022 const double kConservativeGcSpeedInBytesPerMillisecond = 200000; 4023 if (mutator_speed == 0) return kMinMutatorUtilization; 4024 if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond; 4025 // Derivation: 4026 // mutator_utilization = mutator_time / (mutator_time + gc_time) 4027 // mutator_time = 1 / mutator_speed 4028 // gc_time = 1 / gc_speed 4029 // mutator_utilization = (1 / mutator_speed) / 4030 // (1 / mutator_speed + 1 / gc_speed) 4031 // mutator_utilization = gc_speed / (mutator_speed + gc_speed) 4032 return gc_speed / (mutator_speed + gc_speed); 4033 } 4034 4035 4036 double Heap::YoungGenerationMutatorUtilization() { 4037 double mutator_speed = static_cast<double>( 4038 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); 4039 double gc_speed = static_cast<double>( 4040 tracer()->ScavengeSpeedInBytesPerMillisecond(kForSurvivedObjects)); 4041 double result = ComputeMutatorUtilization(mutator_speed, gc_speed); 4042 if (FLAG_trace_mutator_utilization) { 4043 PrintIsolate(isolate(), 4044 "Young generation mutator utilization = %.3f (" 4045 "mutator_speed=%.f, gc_speed=%.f)\n", 4046 result, mutator_speed, gc_speed); 4047 } 4048 return result; 4049 } 4050 4051 4052 double Heap::OldGenerationMutatorUtilization() { 4053 double mutator_speed = static_cast<double>( 4054 tracer()->OldGenerationAllocationThroughputInBytesPerMillisecond()); 4055 double gc_speed = static_cast<double>( 4056 tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond()); 4057 double result = ComputeMutatorUtilization(mutator_speed, gc_speed); 4058 if (FLAG_trace_mutator_utilization) { 4059 PrintIsolate(isolate(), 4060 "Old generation mutator utilization = %.3f (" 4061 "mutator_speed=%.f, gc_speed=%.f)\n", 4062 result, mutator_speed, gc_speed); 4063 } 4064 return result; 4065 } 4066 4067 4068 bool Heap::HasLowYoungGenerationAllocationRate() { 4069 const double high_mutator_utilization = 0.993; 4070 return YoungGenerationMutatorUtilization() > high_mutator_utilization; 4071 } 4072 4073 4074 bool Heap::HasLowOldGenerationAllocationRate() { 4075 const double high_mutator_utilization = 0.993; 4076 return OldGenerationMutatorUtilization() > high_mutator_utilization; 4077 } 4078 4079 4080 bool Heap::HasLowAllocationRate() { 4081 return HasLowYoungGenerationAllocationRate() && 4082 HasLowOldGenerationAllocationRate(); 4083 } 4084 4085 4086 bool Heap::HasHighFragmentation() { 4087 intptr_t used = PromotedSpaceSizeOfObjects(); 4088 intptr_t committed = CommittedOldGenerationMemory(); 4089 return HasHighFragmentation(used, committed); 4090 } 4091 4092 4093 bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) { 4094 const intptr_t kSlack = 16 * MB; 4095 // Fragmentation is high if committed > 2 * used + kSlack. 4096 // Rewrite the exression to avoid overflow. 4097 return committed - used > used + kSlack; 4098 } 4099 4100 4101 void Heap::ReduceNewSpaceSize() { 4102 // TODO(ulan): Unify this constant with the similar constant in 4103 // GCIdleTimeHandler once the change is merged to 4.5. 4104 static const size_t kLowAllocationThroughput = 1000; 4105 const size_t allocation_throughput = 4106 tracer()->CurrentAllocationThroughputInBytesPerMillisecond(); 4107 4108 if (FLAG_predictable) return; 4109 4110 if (ShouldReduceMemory() || 4111 ((allocation_throughput != 0) && 4112 (allocation_throughput < kLowAllocationThroughput))) { 4113 new_space_.Shrink(); 4114 UncommitFromSpace(); 4115 } 4116 } 4117 4118 4119 void Heap::FinalizeIncrementalMarkingIfComplete(const char* comment) { 4120 if (incremental_marking()->IsMarking() && 4121 (incremental_marking()->IsReadyToOverApproximateWeakClosure() || 4122 (!incremental_marking()->finalize_marking_completed() && 4123 mark_compact_collector()->marking_deque()->IsEmpty()))) { 4124 FinalizeIncrementalMarking(comment); 4125 } else if (incremental_marking()->IsComplete() || 4126 (mark_compact_collector()->marking_deque()->IsEmpty())) { 4127 CollectAllGarbage(current_gc_flags_, comment); 4128 } 4129 } 4130 4131 4132 bool Heap::TryFinalizeIdleIncrementalMarking(double idle_time_in_ms) { 4133 size_t size_of_objects = static_cast<size_t>(SizeOfObjects()); 4134 size_t final_incremental_mark_compact_speed_in_bytes_per_ms = 4135 static_cast<size_t>( 4136 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); 4137 if (incremental_marking()->IsReadyToOverApproximateWeakClosure() || 4138 (!incremental_marking()->finalize_marking_completed() && 4139 mark_compact_collector()->marking_deque()->IsEmpty() && 4140 gc_idle_time_handler_->ShouldDoOverApproximateWeakClosure( 4141 static_cast<size_t>(idle_time_in_ms)))) { 4142 FinalizeIncrementalMarking( 4143 "Idle notification: finalize incremental marking"); 4144 return true; 4145 } else if (incremental_marking()->IsComplete() || 4146 (mark_compact_collector()->marking_deque()->IsEmpty() && 4147 gc_idle_time_handler_->ShouldDoFinalIncrementalMarkCompact( 4148 static_cast<size_t>(idle_time_in_ms), size_of_objects, 4149 final_incremental_mark_compact_speed_in_bytes_per_ms))) { 4150 CollectAllGarbage(current_gc_flags_, 4151 "idle notification: finalize incremental marking"); 4152 return true; 4153 } 4154 return false; 4155 } 4156 4157 4158 GCIdleTimeHeapState Heap::ComputeHeapState() { 4159 GCIdleTimeHeapState heap_state; 4160 heap_state.contexts_disposed = contexts_disposed_; 4161 heap_state.contexts_disposal_rate = 4162 tracer()->ContextDisposalRateInMilliseconds(); 4163 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); 4164 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); 4165 return heap_state; 4166 } 4167 4168 4169 bool Heap::PerformIdleTimeAction(GCIdleTimeAction action, 4170 GCIdleTimeHeapState heap_state, 4171 double deadline_in_ms) { 4172 bool result = false; 4173 switch (action.type) { 4174 case DONE: 4175 result = true; 4176 break; 4177 case DO_INCREMENTAL_STEP: { 4178 if (incremental_marking()->incremental_marking_job()->IdleTaskPending()) { 4179 result = true; 4180 } else { 4181 incremental_marking() 4182 ->incremental_marking_job() 4183 ->NotifyIdleTaskProgress(); 4184 result = IncrementalMarkingJob::IdleTask::Step(this, deadline_in_ms) == 4185 IncrementalMarkingJob::IdleTask::kDone; 4186 } 4187 break; 4188 } 4189 case DO_FULL_GC: { 4190 DCHECK(contexts_disposed_ > 0); 4191 HistogramTimerScope scope(isolate_->counters()->gc_context()); 4192 CollectAllGarbage(kNoGCFlags, "idle notification: contexts disposed"); 4193 break; 4194 } 4195 case DO_NOTHING: 4196 break; 4197 } 4198 4199 return result; 4200 } 4201 4202 4203 void Heap::IdleNotificationEpilogue(GCIdleTimeAction action, 4204 GCIdleTimeHeapState heap_state, 4205 double start_ms, double deadline_in_ms) { 4206 double idle_time_in_ms = deadline_in_ms - start_ms; 4207 double current_time = MonotonicallyIncreasingTimeInMs(); 4208 last_idle_notification_time_ = current_time; 4209 double deadline_difference = deadline_in_ms - current_time; 4210 4211 contexts_disposed_ = 0; 4212 4213 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( 4214 static_cast<int>(idle_time_in_ms)); 4215 4216 if (deadline_in_ms - start_ms > 4217 GCIdleTimeHandler::kMaxFrameRenderingIdleTime) { 4218 int committed_memory = static_cast<int>(CommittedMemory() / KB); 4219 int used_memory = static_cast<int>(heap_state.size_of_objects / KB); 4220 isolate()->counters()->aggregated_memory_heap_committed()->AddSample( 4221 start_ms, committed_memory); 4222 isolate()->counters()->aggregated_memory_heap_used()->AddSample( 4223 start_ms, used_memory); 4224 } 4225 4226 if (deadline_difference >= 0) { 4227 if (action.type != DONE && action.type != DO_NOTHING) { 4228 isolate()->counters()->gc_idle_time_limit_undershot()->AddSample( 4229 static_cast<int>(deadline_difference)); 4230 } 4231 } else { 4232 isolate()->counters()->gc_idle_time_limit_overshot()->AddSample( 4233 static_cast<int>(-deadline_difference)); 4234 } 4235 4236 if ((FLAG_trace_idle_notification && action.type > DO_NOTHING) || 4237 FLAG_trace_idle_notification_verbose) { 4238 PrintIsolate(isolate_, "%8.0f ms: ", isolate()->time_millis_since_init()); 4239 PrintF( 4240 "Idle notification: requested idle time %.2f ms, used idle time %.2f " 4241 "ms, deadline usage %.2f ms [", 4242 idle_time_in_ms, idle_time_in_ms - deadline_difference, 4243 deadline_difference); 4244 action.Print(); 4245 PrintF("]"); 4246 if (FLAG_trace_idle_notification_verbose) { 4247 PrintF("["); 4248 heap_state.Print(); 4249 PrintF("]"); 4250 } 4251 PrintF("\n"); 4252 } 4253 } 4254 4255 4256 double Heap::MonotonicallyIncreasingTimeInMs() { 4257 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * 4258 static_cast<double>(base::Time::kMillisecondsPerSecond); 4259 } 4260 4261 4262 bool Heap::IdleNotification(int idle_time_in_ms) { 4263 return IdleNotification( 4264 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + 4265 (static_cast<double>(idle_time_in_ms) / 4266 static_cast<double>(base::Time::kMillisecondsPerSecond))); 4267 } 4268 4269 4270 bool Heap::IdleNotification(double deadline_in_seconds) { 4271 CHECK(HasBeenSetUp()); 4272 double deadline_in_ms = 4273 deadline_in_seconds * 4274 static_cast<double>(base::Time::kMillisecondsPerSecond); 4275 HistogramTimerScope idle_notification_scope( 4276 isolate_->counters()->gc_idle_notification()); 4277 double start_ms = MonotonicallyIncreasingTimeInMs(); 4278 double idle_time_in_ms = deadline_in_ms - start_ms; 4279 4280 tracer()->SampleAllocation(start_ms, NewSpaceAllocationCounter(), 4281 OldGenerationAllocationCounter()); 4282 4283 GCIdleTimeHeapState heap_state = ComputeHeapState(); 4284 4285 GCIdleTimeAction action = 4286 gc_idle_time_handler_->Compute(idle_time_in_ms, heap_state); 4287 4288 bool result = PerformIdleTimeAction(action, heap_state, deadline_in_ms); 4289 4290 IdleNotificationEpilogue(action, heap_state, start_ms, deadline_in_ms); 4291 return result; 4292 } 4293 4294 4295 bool Heap::RecentIdleNotificationHappened() { 4296 return (last_idle_notification_time_ + 4297 GCIdleTimeHandler::kMaxScheduledIdleTime) > 4298 MonotonicallyIncreasingTimeInMs(); 4299 } 4300 4301 4302 #ifdef DEBUG 4303 4304 void Heap::Print() { 4305 if (!HasBeenSetUp()) return; 4306 isolate()->PrintStack(stdout); 4307 AllSpaces spaces(this); 4308 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { 4309 space->Print(); 4310 } 4311 } 4312 4313 4314 void Heap::ReportCodeStatistics(const char* title) { 4315 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); 4316 PagedSpace::ResetCodeStatistics(isolate()); 4317 // We do not look for code in new space, map space, or old space. If code 4318 // somehow ends up in those spaces, we would miss it here. 4319 code_space_->CollectCodeStatistics(); 4320 lo_space_->CollectCodeStatistics(); 4321 PagedSpace::ReportCodeStatistics(isolate()); 4322 } 4323 4324 4325 // This function expects that NewSpace's allocated objects histogram is 4326 // populated (via a call to CollectStatistics or else as a side effect of a 4327 // just-completed scavenge collection). 4328 void Heap::ReportHeapStatistics(const char* title) { 4329 USE(title); 4330 PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", title, 4331 gc_count_); 4332 PrintF("old_generation_allocation_limit_ %" V8_PTR_PREFIX "d\n", 4333 old_generation_allocation_limit_); 4334 4335 PrintF("\n"); 4336 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles(isolate_)); 4337 isolate_->global_handles()->PrintStats(); 4338 PrintF("\n"); 4339 4340 PrintF("Heap statistics : "); 4341 isolate_->memory_allocator()->ReportStatistics(); 4342 PrintF("To space : "); 4343 new_space_.ReportStatistics(); 4344 PrintF("Old space : "); 4345 old_space_->ReportStatistics(); 4346 PrintF("Code space : "); 4347 code_space_->ReportStatistics(); 4348 PrintF("Map space : "); 4349 map_space_->ReportStatistics(); 4350 PrintF("Large object space : "); 4351 lo_space_->ReportStatistics(); 4352 PrintF(">>>>>> ========================================= >>>>>>\n"); 4353 } 4354 4355 #endif // DEBUG 4356 4357 bool Heap::Contains(HeapObject* value) { return Contains(value->address()); } 4358 4359 4360 bool Heap::Contains(Address addr) { 4361 if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) return false; 4362 return HasBeenSetUp() && 4363 (new_space_.ToSpaceContains(addr) || old_space_->Contains(addr) || 4364 code_space_->Contains(addr) || map_space_->Contains(addr) || 4365 lo_space_->SlowContains(addr)); 4366 } 4367 4368 4369 bool Heap::InSpace(HeapObject* value, AllocationSpace space) { 4370 return InSpace(value->address(), space); 4371 } 4372 4373 4374 bool Heap::InSpace(Address addr, AllocationSpace space) { 4375 if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) return false; 4376 if (!HasBeenSetUp()) return false; 4377 4378 switch (space) { 4379 case NEW_SPACE: 4380 return new_space_.ToSpaceContains(addr); 4381 case OLD_SPACE: 4382 return old_space_->Contains(addr); 4383 case CODE_SPACE: 4384 return code_space_->Contains(addr); 4385 case MAP_SPACE: 4386 return map_space_->Contains(addr); 4387 case LO_SPACE: 4388 return lo_space_->SlowContains(addr); 4389 } 4390 UNREACHABLE(); 4391 return false; 4392 } 4393 4394 4395 bool Heap::IsValidAllocationSpace(AllocationSpace space) { 4396 switch (space) { 4397 case NEW_SPACE: 4398 case OLD_SPACE: 4399 case CODE_SPACE: 4400 case MAP_SPACE: 4401 case LO_SPACE: 4402 return true; 4403 default: 4404 return false; 4405 } 4406 } 4407 4408 4409 bool Heap::RootIsImmortalImmovable(int root_index) { 4410 switch (root_index) { 4411 #define IMMORTAL_IMMOVABLE_ROOT(name) case Heap::k##name##RootIndex: 4412 IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT) 4413 #undef IMMORTAL_IMMOVABLE_ROOT 4414 #define INTERNALIZED_STRING(name, value) case Heap::k##name##RootIndex: 4415 INTERNALIZED_STRING_LIST(INTERNALIZED_STRING) 4416 #undef INTERNALIZED_STRING 4417 #define STRING_TYPE(NAME, size, name, Name) case Heap::k##Name##MapRootIndex: 4418 STRING_TYPE_LIST(STRING_TYPE) 4419 #undef STRING_TYPE 4420 return true; 4421 default: 4422 return false; 4423 } 4424 } 4425 4426 4427 #ifdef VERIFY_HEAP 4428 void Heap::Verify() { 4429 CHECK(HasBeenSetUp()); 4430 HandleScope scope(isolate()); 4431 4432 store_buffer()->Verify(); 4433 4434 if (mark_compact_collector()->sweeping_in_progress()) { 4435 // We have to wait here for the sweeper threads to have an iterable heap. 4436 mark_compact_collector()->EnsureSweepingCompleted(); 4437 } 4438 4439 VerifyPointersVisitor visitor; 4440 IterateRoots(&visitor, VISIT_ONLY_STRONG); 4441 4442 VerifySmisVisitor smis_visitor; 4443 IterateSmiRoots(&smis_visitor); 4444 4445 new_space_.Verify(); 4446 4447 old_space_->Verify(&visitor); 4448 map_space_->Verify(&visitor); 4449 4450 VerifyPointersVisitor no_dirty_regions_visitor; 4451 code_space_->Verify(&no_dirty_regions_visitor); 4452 4453 lo_space_->Verify(); 4454 4455 mark_compact_collector()->VerifyWeakEmbeddedObjectsInCode(); 4456 if (FLAG_omit_map_checks_for_leaf_maps) { 4457 mark_compact_collector()->VerifyOmittedMapChecks(); 4458 } 4459 } 4460 #endif 4461 4462 4463 void Heap::ZapFromSpace() { 4464 if (!new_space_.IsFromSpaceCommitted()) return; 4465 NewSpacePageIterator it(new_space_.FromSpaceStart(), 4466 new_space_.FromSpaceEnd()); 4467 while (it.has_next()) { 4468 NewSpacePage* page = it.next(); 4469 for (Address cursor = page->area_start(), limit = page->area_end(); 4470 cursor < limit; cursor += kPointerSize) { 4471 Memory::Address_at(cursor) = kFromSpaceZapValue; 4472 } 4473 } 4474 } 4475 4476 4477 void Heap::IterateAndMarkPointersToFromSpace(HeapObject* object, Address start, 4478 Address end, bool record_slots, 4479 ObjectSlotCallback callback) { 4480 Address slot_address = start; 4481 4482 while (slot_address < end) { 4483 Object** slot = reinterpret_cast<Object**>(slot_address); 4484 Object* target = *slot; 4485 // If the store buffer becomes overfull we mark pages as being exempt from 4486 // the store buffer. These pages are scanned to find pointers that point 4487 // to the new space. In that case we may hit newly promoted objects and 4488 // fix the pointers before the promotion queue gets to them. Thus the 'if'. 4489 if (target->IsHeapObject()) { 4490 if (Heap::InFromSpace(target)) { 4491 callback(reinterpret_cast<HeapObject**>(slot), 4492 HeapObject::cast(target)); 4493 Object* new_target = *slot; 4494 if (InNewSpace(new_target)) { 4495 SLOW_DCHECK(Heap::InToSpace(new_target)); 4496 SLOW_DCHECK(new_target->IsHeapObject()); 4497 store_buffer_.EnterDirectlyIntoStoreBuffer( 4498 reinterpret_cast<Address>(slot)); 4499 } 4500 SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); 4501 } else if (record_slots && 4502 MarkCompactCollector::IsOnEvacuationCandidate(target)) { 4503 mark_compact_collector()->RecordSlot(object, slot, target); 4504 } 4505 } 4506 slot_address += kPointerSize; 4507 } 4508 } 4509 4510 4511 class IteratePointersToFromSpaceVisitor final : public ObjectVisitor { 4512 public: 4513 IteratePointersToFromSpaceVisitor(Heap* heap, HeapObject* target, 4514 bool record_slots, 4515 ObjectSlotCallback callback) 4516 : heap_(heap), 4517 target_(target), 4518 record_slots_(record_slots), 4519 callback_(callback) {} 4520 4521 V8_INLINE void VisitPointers(Object** start, Object** end) override { 4522 heap_->IterateAndMarkPointersToFromSpace( 4523 target_, reinterpret_cast<Address>(start), 4524 reinterpret_cast<Address>(end), record_slots_, callback_); 4525 } 4526 4527 V8_INLINE void VisitCodeEntry(Address code_entry_slot) override {} 4528 4529 private: 4530 Heap* heap_; 4531 HeapObject* target_; 4532 bool record_slots_; 4533 ObjectSlotCallback callback_; 4534 }; 4535 4536 4537 void Heap::IteratePointersToFromSpace(HeapObject* target, int size, 4538 ObjectSlotCallback callback) { 4539 // We are not collecting slots on new space objects during mutation 4540 // thus we have to scan for pointers to evacuation candidates when we 4541 // promote objects. But we should not record any slots in non-black 4542 // objects. Grey object's slots would be rescanned. 4543 // White object might not survive until the end of collection 4544 // it would be a violation of the invariant to record it's slots. 4545 bool record_slots = false; 4546 if (incremental_marking()->IsCompacting()) { 4547 MarkBit mark_bit = Marking::MarkBitFrom(target); 4548 record_slots = Marking::IsBlack(mark_bit); 4549 } 4550 4551 IteratePointersToFromSpaceVisitor visitor(this, target, record_slots, 4552 callback); 4553 target->IterateBody(target->map()->instance_type(), size, &visitor); 4554 } 4555 4556 4557 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { 4558 IterateStrongRoots(v, mode); 4559 IterateWeakRoots(v, mode); 4560 } 4561 4562 4563 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { 4564 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); 4565 v->Synchronize(VisitorSynchronization::kStringTable); 4566 if (mode != VISIT_ALL_IN_SCAVENGE && mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { 4567 // Scavenge collections have special processing for this. 4568 external_string_table_.Iterate(v); 4569 } 4570 v->Synchronize(VisitorSynchronization::kExternalStringsTable); 4571 } 4572 4573 4574 void Heap::IterateSmiRoots(ObjectVisitor* v) { 4575 // Acquire execution access since we are going to read stack limit values. 4576 ExecutionAccess access(isolate()); 4577 v->VisitPointers(&roots_[kSmiRootsStart], &roots_[kRootListLength]); 4578 v->Synchronize(VisitorSynchronization::kSmiRootList); 4579 } 4580 4581 4582 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { 4583 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); 4584 v->Synchronize(VisitorSynchronization::kStrongRootList); 4585 4586 isolate_->bootstrapper()->Iterate(v); 4587 v->Synchronize(VisitorSynchronization::kBootstrapper); 4588 isolate_->Iterate(v); 4589 v->Synchronize(VisitorSynchronization::kTop); 4590 Relocatable::Iterate(isolate_, v); 4591 v->Synchronize(VisitorSynchronization::kRelocatable); 4592 4593 if (isolate_->deoptimizer_data() != NULL) { 4594 isolate_->deoptimizer_data()->Iterate(v); 4595 } 4596 v->Synchronize(VisitorSynchronization::kDebug); 4597 isolate_->compilation_cache()->Iterate(v); 4598 v->Synchronize(VisitorSynchronization::kCompilationCache); 4599 4600 // Iterate over local handles in handle scopes. 4601 isolate_->handle_scope_implementer()->Iterate(v); 4602 isolate_->IterateDeferredHandles(v); 4603 v->Synchronize(VisitorSynchronization::kHandleScope); 4604 4605 // Iterate over the builtin code objects and code stubs in the 4606 // heap. Note that it is not necessary to iterate over code objects 4607 // on scavenge collections. 4608 if (mode != VISIT_ALL_IN_SCAVENGE) { 4609 isolate_->builtins()->IterateBuiltins(v); 4610 } 4611 v->Synchronize(VisitorSynchronization::kBuiltins); 4612 4613 // Iterate over global handles. 4614 switch (mode) { 4615 case VISIT_ONLY_STRONG: 4616 isolate_->global_handles()->IterateStrongRoots(v); 4617 break; 4618 case VISIT_ALL_IN_SCAVENGE: 4619 isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v); 4620 break; 4621 case VISIT_ALL_IN_SWEEP_NEWSPACE: 4622 case VISIT_ALL: 4623 isolate_->global_handles()->IterateAllRoots(v); 4624 break; 4625 } 4626 v->Synchronize(VisitorSynchronization::kGlobalHandles); 4627 4628 // Iterate over eternal handles. 4629 if (mode == VISIT_ALL_IN_SCAVENGE) { 4630 isolate_->eternal_handles()->IterateNewSpaceRoots(v); 4631 } else { 4632 isolate_->eternal_handles()->IterateAllRoots(v); 4633 } 4634 v->Synchronize(VisitorSynchronization::kEternalHandles); 4635 4636 // Iterate over pointers being held by inactive threads. 4637 isolate_->thread_manager()->Iterate(v); 4638 v->Synchronize(VisitorSynchronization::kThreadManager); 4639 4640 // Iterate over other strong roots (currently only identity maps). 4641 for (StrongRootsList* list = strong_roots_list_; list; list = list->next) { 4642 v->VisitPointers(list->start, list->end); 4643 } 4644 v->Synchronize(VisitorSynchronization::kStrongRoots); 4645 4646 // Iterate over the pointers the Serialization/Deserialization code is 4647 // holding. 4648 // During garbage collection this keeps the partial snapshot cache alive. 4649 // During deserialization of the startup snapshot this creates the partial 4650 // snapshot cache and deserializes the objects it refers to. During 4651 // serialization this does nothing, since the partial snapshot cache is 4652 // empty. However the next thing we do is create the partial snapshot, 4653 // filling up the partial snapshot cache with objects it needs as we go. 4654 SerializerDeserializer::Iterate(isolate_, v); 4655 // We don't do a v->Synchronize call here, because in debug mode that will 4656 // output a flag to the snapshot. However at this point the serializer and 4657 // deserializer are deliberately a little unsynchronized (see above) so the 4658 // checking of the sync flag in the snapshot would fail. 4659 } 4660 4661 4662 // TODO(1236194): Since the heap size is configurable on the command line 4663 // and through the API, we should gracefully handle the case that the heap 4664 // size is not big enough to fit all the initial objects. 4665 bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size, 4666 int max_executable_size, size_t code_range_size) { 4667 if (HasBeenSetUp()) return false; 4668 4669 // Overwrite default configuration. 4670 if (max_semi_space_size > 0) { 4671 max_semi_space_size_ = max_semi_space_size * MB; 4672 } 4673 if (max_old_space_size > 0) { 4674 max_old_generation_size_ = static_cast<intptr_t>(max_old_space_size) * MB; 4675 } 4676 if (max_executable_size > 0) { 4677 max_executable_size_ = static_cast<intptr_t>(max_executable_size) * MB; 4678 } 4679 4680 // If max space size flags are specified overwrite the configuration. 4681 if (FLAG_max_semi_space_size > 0) { 4682 max_semi_space_size_ = FLAG_max_semi_space_size * MB; 4683 } 4684 if (FLAG_max_old_space_size > 0) { 4685 max_old_generation_size_ = 4686 static_cast<intptr_t>(FLAG_max_old_space_size) * MB; 4687 } 4688 if (FLAG_max_executable_size > 0) { 4689 max_executable_size_ = static_cast<intptr_t>(FLAG_max_executable_size) * MB; 4690 } 4691 4692 if (Page::kPageSize > MB) { 4693 max_semi_space_size_ = ROUND_UP(max_semi_space_size_, Page::kPageSize); 4694 max_old_generation_size_ = 4695 ROUND_UP(max_old_generation_size_, Page::kPageSize); 4696 max_executable_size_ = ROUND_UP(max_executable_size_, Page::kPageSize); 4697 } 4698 4699 if (FLAG_stress_compaction) { 4700 // This will cause more frequent GCs when stressing. 4701 max_semi_space_size_ = Page::kPageSize; 4702 } 4703 4704 if (isolate()->snapshot_available()) { 4705 // If we are using a snapshot we always reserve the default amount 4706 // of memory for each semispace because code in the snapshot has 4707 // write-barrier code that relies on the size and alignment of new 4708 // space. We therefore cannot use a larger max semispace size 4709 // than the default reserved semispace size. 4710 if (max_semi_space_size_ > reserved_semispace_size_) { 4711 max_semi_space_size_ = reserved_semispace_size_; 4712 if (FLAG_trace_gc) { 4713 PrintIsolate(isolate_, 4714 "Max semi-space size cannot be more than %d kbytes\n", 4715 reserved_semispace_size_ >> 10); 4716 } 4717 } 4718 } else { 4719 // If we are not using snapshots we reserve space for the actual 4720 // max semispace size. 4721 reserved_semispace_size_ = max_semi_space_size_; 4722 } 4723 4724 // The new space size must be a power of two to support single-bit testing 4725 // for containment. 4726 max_semi_space_size_ = 4727 base::bits::RoundUpToPowerOfTwo32(max_semi_space_size_); 4728 reserved_semispace_size_ = 4729 base::bits::RoundUpToPowerOfTwo32(reserved_semispace_size_); 4730 4731 if (FLAG_min_semi_space_size > 0) { 4732 int initial_semispace_size = FLAG_min_semi_space_size * MB; 4733 if (initial_semispace_size > max_semi_space_size_) { 4734 initial_semispace_size_ = max_semi_space_size_; 4735 if (FLAG_trace_gc) { 4736 PrintIsolate(isolate_, 4737 "Min semi-space size cannot be more than the maximum " 4738 "semi-space size of %d MB\n", 4739 max_semi_space_size_ / MB); 4740 } 4741 } else { 4742 initial_semispace_size_ = 4743 ROUND_UP(initial_semispace_size, Page::kPageSize); 4744 } 4745 } 4746 4747 initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_); 4748 4749 if (FLAG_target_semi_space_size > 0) { 4750 int target_semispace_size = FLAG_target_semi_space_size * MB; 4751 if (target_semispace_size < initial_semispace_size_) { 4752 target_semispace_size_ = initial_semispace_size_; 4753 if (FLAG_trace_gc) { 4754 PrintIsolate(isolate_, 4755 "Target semi-space size cannot be less than the minimum " 4756 "semi-space size of %d MB\n", 4757 initial_semispace_size_ / MB); 4758 } 4759 } else if (target_semispace_size > max_semi_space_size_) { 4760 target_semispace_size_ = max_semi_space_size_; 4761 if (FLAG_trace_gc) { 4762 PrintIsolate(isolate_, 4763 "Target semi-space size cannot be less than the maximum " 4764 "semi-space size of %d MB\n", 4765 max_semi_space_size_ / MB); 4766 } 4767 } else { 4768 target_semispace_size_ = ROUND_UP(target_semispace_size, Page::kPageSize); 4769 } 4770 } 4771 4772 target_semispace_size_ = Max(initial_semispace_size_, target_semispace_size_); 4773 4774 if (FLAG_semi_space_growth_factor < 2) { 4775 FLAG_semi_space_growth_factor = 2; 4776 } 4777 4778 // The old generation is paged and needs at least one page for each space. 4779 int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; 4780 max_old_generation_size_ = 4781 Max(static_cast<intptr_t>(paged_space_count * Page::kPageSize), 4782 max_old_generation_size_); 4783 4784 // The max executable size must be less than or equal to the max old 4785 // generation size. 4786 if (max_executable_size_ > max_old_generation_size_) { 4787 max_executable_size_ = max_old_generation_size_; 4788 } 4789 4790 if (FLAG_initial_old_space_size > 0) { 4791 initial_old_generation_size_ = FLAG_initial_old_space_size * MB; 4792 } else { 4793 initial_old_generation_size_ = 4794 max_old_generation_size_ / kInitalOldGenerationLimitFactor; 4795 } 4796 old_generation_allocation_limit_ = initial_old_generation_size_; 4797 4798 // We rely on being able to allocate new arrays in paged spaces. 4799 DCHECK(Page::kMaxRegularHeapObjectSize >= 4800 (JSArray::kSize + 4801 FixedArray::SizeFor(JSArray::kInitialMaxFastElementArray) + 4802 AllocationMemento::kSize)); 4803 4804 code_range_size_ = code_range_size * MB; 4805 4806 configured_ = true; 4807 return true; 4808 } 4809 4810 4811 void Heap::AddToRingBuffer(const char* string) { 4812 size_t first_part = 4813 Min(strlen(string), kTraceRingBufferSize - ring_buffer_end_); 4814 memcpy(trace_ring_buffer_ + ring_buffer_end_, string, first_part); 4815 ring_buffer_end_ += first_part; 4816 if (first_part < strlen(string)) { 4817 ring_buffer_full_ = true; 4818 size_t second_part = strlen(string) - first_part; 4819 memcpy(trace_ring_buffer_, string + first_part, second_part); 4820 ring_buffer_end_ = second_part; 4821 } 4822 } 4823 4824 4825 void Heap::GetFromRingBuffer(char* buffer) { 4826 size_t copied = 0; 4827 if (ring_buffer_full_) { 4828 copied = kTraceRingBufferSize - ring_buffer_end_; 4829 memcpy(buffer, trace_ring_buffer_ + ring_buffer_end_, copied); 4830 } 4831 memcpy(buffer + copied, trace_ring_buffer_, ring_buffer_end_); 4832 } 4833 4834 4835 bool Heap::ConfigureHeapDefault() { return ConfigureHeap(0, 0, 0, 0); } 4836 4837 4838 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) { 4839 *stats->start_marker = HeapStats::kStartMarker; 4840 *stats->end_marker = HeapStats::kEndMarker; 4841 *stats->new_space_size = new_space_.SizeAsInt(); 4842 *stats->new_space_capacity = static_cast<int>(new_space_.Capacity()); 4843 *stats->old_space_size = old_space_->SizeOfObjects(); 4844 *stats->old_space_capacity = old_space_->Capacity(); 4845 *stats->code_space_size = code_space_->SizeOfObjects(); 4846 *stats->code_space_capacity = code_space_->Capacity(); 4847 *stats->map_space_size = map_space_->SizeOfObjects(); 4848 *stats->map_space_capacity = map_space_->Capacity(); 4849 *stats->lo_space_size = lo_space_->Size(); 4850 isolate_->global_handles()->RecordStats(stats); 4851 *stats->memory_allocator_size = isolate()->memory_allocator()->Size(); 4852 *stats->memory_allocator_capacity = 4853 isolate()->memory_allocator()->Size() + 4854 isolate()->memory_allocator()->Available(); 4855 *stats->os_error = base::OS::GetLastError(); 4856 isolate()->memory_allocator()->Available(); 4857 if (take_snapshot) { 4858 HeapIterator iterator(this); 4859 for (HeapObject* obj = iterator.next(); obj != NULL; 4860 obj = iterator.next()) { 4861 InstanceType type = obj->map()->instance_type(); 4862 DCHECK(0 <= type && type <= LAST_TYPE); 4863 stats->objects_per_type[type]++; 4864 stats->size_per_type[type] += obj->Size(); 4865 } 4866 } 4867 if (stats->last_few_messages != NULL) 4868 GetFromRingBuffer(stats->last_few_messages); 4869 if (stats->js_stacktrace != NULL) { 4870 FixedStringAllocator fixed(stats->js_stacktrace, kStacktraceBufferSize - 1); 4871 StringStream accumulator(&fixed, StringStream::kPrintObjectConcise); 4872 if (gc_state() == Heap::NOT_IN_GC) { 4873 isolate()->PrintStack(&accumulator, Isolate::kPrintStackVerbose); 4874 } else { 4875 accumulator.Add("Cannot get stack trace in GC."); 4876 } 4877 } 4878 } 4879 4880 4881 intptr_t Heap::PromotedSpaceSizeOfObjects() { 4882 return old_space_->SizeOfObjects() + code_space_->SizeOfObjects() + 4883 map_space_->SizeOfObjects() + lo_space_->SizeOfObjects(); 4884 } 4885 4886 4887 int64_t Heap::PromotedExternalMemorySize() { 4888 if (amount_of_external_allocated_memory_ <= 4889 amount_of_external_allocated_memory_at_last_global_gc_) 4890 return 0; 4891 return amount_of_external_allocated_memory_ - 4892 amount_of_external_allocated_memory_at_last_global_gc_; 4893 } 4894 4895 4896 const double Heap::kMinHeapGrowingFactor = 1.1; 4897 const double Heap::kMaxHeapGrowingFactor = 4.0; 4898 const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0; 4899 const double Heap::kMaxHeapGrowingFactorIdle = 1.5; 4900 const double Heap::kTargetMutatorUtilization = 0.97; 4901 4902 4903 // Given GC speed in bytes per ms, the allocation throughput in bytes per ms 4904 // (mutator speed), this function returns the heap growing factor that will 4905 // achieve the kTargetMutatorUtilisation if the GC speed and the mutator speed 4906 // remain the same until the next GC. 4907 // 4908 // For a fixed time-frame T = TM + TG, the mutator utilization is the ratio 4909 // TM / (TM + TG), where TM is the time spent in the mutator and TG is the 4910 // time spent in the garbage collector. 4911 // 4912 // Let MU be kTargetMutatorUtilisation, the desired mutator utilization for the 4913 // time-frame from the end of the current GC to the end of the next GC. Based 4914 // on the MU we can compute the heap growing factor F as 4915 // 4916 // F = R * (1 - MU) / (R * (1 - MU) - MU), where R = gc_speed / mutator_speed. 4917 // 4918 // This formula can be derived as follows. 4919 // 4920 // F = Limit / Live by definition, where the Limit is the allocation limit, 4921 // and the Live is size of live objects. 4922 // Lets assume that we already know the Limit. Then: 4923 // TG = Limit / gc_speed 4924 // TM = (TM + TG) * MU, by definition of MU. 4925 // TM = TG * MU / (1 - MU) 4926 // TM = Limit * MU / (gc_speed * (1 - MU)) 4927 // On the other hand, if the allocation throughput remains constant: 4928 // Limit = Live + TM * allocation_throughput = Live + TM * mutator_speed 4929 // Solving it for TM, we get 4930 // TM = (Limit - Live) / mutator_speed 4931 // Combining the two equation for TM: 4932 // (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU)) 4933 // (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU)) 4934 // substitute R = gc_speed / mutator_speed 4935 // (Limit - Live) = Limit * MU / (R * (1 - MU)) 4936 // substitute F = Limit / Live 4937 // F - 1 = F * MU / (R * (1 - MU)) 4938 // F - F * MU / (R * (1 - MU)) = 1 4939 // F * (1 - MU / (R * (1 - MU))) = 1 4940 // F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1 4941 // F = R * (1 - MU) / (R * (1 - MU) - MU) 4942 double Heap::HeapGrowingFactor(double gc_speed, double mutator_speed) { 4943 if (gc_speed == 0 || mutator_speed == 0) return kMaxHeapGrowingFactor; 4944 4945 const double speed_ratio = gc_speed / mutator_speed; 4946 const double mu = kTargetMutatorUtilization; 4947 4948 const double a = speed_ratio * (1 - mu); 4949 const double b = speed_ratio * (1 - mu) - mu; 4950 4951 // The factor is a / b, but we need to check for small b first. 4952 double factor = 4953 (a < b * kMaxHeapGrowingFactor) ? a / b : kMaxHeapGrowingFactor; 4954 factor = Min(factor, kMaxHeapGrowingFactor); 4955 factor = Max(factor, kMinHeapGrowingFactor); 4956 return factor; 4957 } 4958 4959 4960 intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, 4961 intptr_t old_gen_size) { 4962 CHECK(factor > 1.0); 4963 CHECK(old_gen_size > 0); 4964 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); 4965 limit = Max(limit, old_gen_size + kMinimumOldGenerationAllocationLimit); 4966 limit += new_space_.Capacity(); 4967 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; 4968 return Min(limit, halfway_to_the_max); 4969 } 4970 4971 4972 void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, 4973 double gc_speed, 4974 double mutator_speed) { 4975 const double kConservativeHeapGrowingFactor = 1.3; 4976 4977 double factor = HeapGrowingFactor(gc_speed, mutator_speed); 4978 4979 if (FLAG_trace_gc_verbose) { 4980 PrintIsolate(isolate_, 4981 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " 4982 "(gc=%.f, mutator=%.f)\n", 4983 factor, kTargetMutatorUtilization, gc_speed / mutator_speed, 4984 gc_speed, mutator_speed); 4985 } 4986 4987 // We set the old generation growing factor to 2 to grow the heap slower on 4988 // memory-constrained devices. 4989 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice || 4990 FLAG_optimize_for_size) { 4991 factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained); 4992 } 4993 4994 if (memory_reducer_->ShouldGrowHeapSlowly() || optimize_for_memory_usage_) { 4995 factor = Min(factor, kConservativeHeapGrowingFactor); 4996 } 4997 4998 if (FLAG_stress_compaction || ShouldReduceMemory()) { 4999 factor = kMinHeapGrowingFactor; 5000 } 5001 5002 if (FLAG_heap_growing_percent > 0) { 5003 factor = 1.0 + FLAG_heap_growing_percent / 100.0; 5004 } 5005 5006 old_generation_allocation_limit_ = 5007 CalculateOldGenerationAllocationLimit(factor, old_gen_size); 5008 5009 if (FLAG_trace_gc_verbose) { 5010 PrintIsolate(isolate_, "Grow: old size: %" V8_PTR_PREFIX 5011 "d KB, new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n", 5012 old_gen_size / KB, old_generation_allocation_limit_ / KB, 5013 factor); 5014 } 5015 } 5016 5017 5018 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, 5019 double gc_speed, 5020 double mutator_speed) { 5021 double factor = HeapGrowingFactor(gc_speed, mutator_speed); 5022 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); 5023 if (limit < old_generation_allocation_limit_) { 5024 if (FLAG_trace_gc_verbose) { 5025 PrintIsolate(isolate_, "Dampen: old size: %" V8_PTR_PREFIX 5026 "d KB, old limit: %" V8_PTR_PREFIX 5027 "d KB, " 5028 "new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n", 5029 old_gen_size / KB, old_generation_allocation_limit_ / KB, 5030 limit / KB, factor); 5031 } 5032 old_generation_allocation_limit_ = limit; 5033 } 5034 } 5035 5036 5037 void Heap::EnableInlineAllocation() { 5038 if (!inline_allocation_disabled_) return; 5039 inline_allocation_disabled_ = false; 5040 5041 // Update inline allocation limit for new space. 5042 new_space()->UpdateInlineAllocationLimit(0); 5043 } 5044 5045 5046 void Heap::DisableInlineAllocation() { 5047 if (inline_allocation_disabled_) return; 5048 inline_allocation_disabled_ = true; 5049 5050 // Update inline allocation limit for new space. 5051 new_space()->UpdateInlineAllocationLimit(0); 5052 5053 // Update inline allocation limit for old spaces. 5054 PagedSpaces spaces(this); 5055 for (PagedSpace* space = spaces.next(); space != NULL; 5056 space = spaces.next()) { 5057 space->EmptyAllocationInfo(); 5058 } 5059 } 5060 5061 5062 V8_DECLARE_ONCE(initialize_gc_once); 5063 5064 static void InitializeGCOnce() { 5065 Scavenger::Initialize(); 5066 StaticScavengeVisitor::Initialize(); 5067 MarkCompactCollector::Initialize(); 5068 } 5069 5070 5071 bool Heap::SetUp() { 5072 #ifdef DEBUG 5073 allocation_timeout_ = FLAG_gc_interval; 5074 #endif 5075 5076 // Initialize heap spaces and initial maps and objects. Whenever something 5077 // goes wrong, just return false. The caller should check the results and 5078 // call Heap::TearDown() to release allocated memory. 5079 // 5080 // If the heap is not yet configured (e.g. through the API), configure it. 5081 // Configuration is based on the flags new-space-size (really the semispace 5082 // size) and old-space-size if set or the initial values of semispace_size_ 5083 // and old_generation_size_ otherwise. 5084 if (!configured_) { 5085 if (!ConfigureHeapDefault()) return false; 5086 } 5087 5088 base::CallOnce(&initialize_gc_once, &InitializeGCOnce); 5089 5090 // Set up memory allocator. 5091 if (!isolate_->memory_allocator()->SetUp(MaxReserved(), MaxExecutableSize())) 5092 return false; 5093 5094 // Initialize incremental marking. 5095 incremental_marking_ = new IncrementalMarking(this); 5096 5097 // Set up new space. 5098 if (!new_space_.SetUp(reserved_semispace_size_, max_semi_space_size_)) { 5099 return false; 5100 } 5101 new_space_top_after_last_gc_ = new_space()->top(); 5102 5103 // Initialize old space. 5104 old_space_ = new OldSpace(this, OLD_SPACE, NOT_EXECUTABLE); 5105 if (old_space_ == NULL) return false; 5106 if (!old_space_->SetUp()) return false; 5107 5108 if (!isolate_->code_range()->SetUp(code_range_size_)) return false; 5109 5110 // Initialize the code space, set its maximum capacity to the old 5111 // generation size. It needs executable memory. 5112 code_space_ = new OldSpace(this, CODE_SPACE, EXECUTABLE); 5113 if (code_space_ == NULL) return false; 5114 if (!code_space_->SetUp()) return false; 5115 5116 // Initialize map space. 5117 map_space_ = new MapSpace(this, MAP_SPACE); 5118 if (map_space_ == NULL) return false; 5119 if (!map_space_->SetUp()) return false; 5120 5121 // The large object code space may contain code or data. We set the memory 5122 // to be non-executable here for safety, but this means we need to enable it 5123 // explicitly when allocating large code objects. 5124 lo_space_ = new LargeObjectSpace(this, LO_SPACE); 5125 if (lo_space_ == NULL) return false; 5126 if (!lo_space_->SetUp()) return false; 5127 5128 // Set up the seed that is used to randomize the string hash function. 5129 DCHECK(hash_seed() == 0); 5130 if (FLAG_randomize_hashes) { 5131 if (FLAG_hash_seed == 0) { 5132 int rnd = isolate()->random_number_generator()->NextInt(); 5133 set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask)); 5134 } else { 5135 set_hash_seed(Smi::FromInt(FLAG_hash_seed)); 5136 } 5137 } 5138 5139 for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount); 5140 i++) { 5141 deferred_counters_[i] = 0; 5142 } 5143 5144 tracer_ = new GCTracer(this); 5145 5146 scavenge_collector_ = new Scavenger(this); 5147 5148 mark_compact_collector_ = new MarkCompactCollector(this); 5149 5150 gc_idle_time_handler_ = new GCIdleTimeHandler(); 5151 5152 memory_reducer_ = new MemoryReducer(this); 5153 5154 object_stats_ = new ObjectStats(this); 5155 object_stats_->ClearObjectStats(true); 5156 5157 scavenge_job_ = new ScavengeJob(); 5158 5159 array_buffer_tracker_ = new ArrayBufferTracker(this); 5160 5161 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); 5162 LOG(isolate_, IntPtrTEvent("heap-available", Available())); 5163 5164 store_buffer()->SetUp(); 5165 5166 mark_compact_collector()->SetUp(); 5167 5168 idle_scavenge_observer_ = new IdleScavengeObserver( 5169 *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask); 5170 new_space()->AddInlineAllocationObserver(idle_scavenge_observer_); 5171 5172 return true; 5173 } 5174 5175 5176 bool Heap::CreateHeapObjects() { 5177 // Create initial maps. 5178 if (!CreateInitialMaps()) return false; 5179 CreateApiObjects(); 5180 5181 // Create initial objects 5182 CreateInitialObjects(); 5183 CHECK_EQ(0u, gc_count_); 5184 5185 set_native_contexts_list(undefined_value()); 5186 set_allocation_sites_list(undefined_value()); 5187 5188 return true; 5189 } 5190 5191 5192 void Heap::SetStackLimits() { 5193 DCHECK(isolate_ != NULL); 5194 DCHECK(isolate_ == isolate()); 5195 // On 64 bit machines, pointers are generally out of range of Smis. We write 5196 // something that looks like an out of range Smi to the GC. 5197 5198 // Set up the special root array entries containing the stack limits. 5199 // These are actually addresses, but the tag makes the GC ignore it. 5200 roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>( 5201 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); 5202 roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>( 5203 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); 5204 } 5205 5206 5207 void Heap::PrintAlloctionsHash() { 5208 uint32_t hash = StringHasher::GetHashCore(raw_allocations_hash_); 5209 PrintF("\n### Allocations = %u, hash = 0x%08x\n", allocations_count(), hash); 5210 } 5211 5212 5213 void Heap::NotifyDeserializationComplete() { 5214 deserialization_complete_ = true; 5215 #ifdef DEBUG 5216 // All pages right after bootstrapping must be marked as never-evacuate. 5217 PagedSpaces spaces(this); 5218 for (PagedSpace* s = spaces.next(); s != NULL; s = spaces.next()) { 5219 PageIterator it(s); 5220 while (it.has_next()) CHECK(it.next()->NeverEvacuate()); 5221 } 5222 #endif // DEBUG 5223 } 5224 5225 5226 void Heap::TearDown() { 5227 #ifdef VERIFY_HEAP 5228 if (FLAG_verify_heap) { 5229 Verify(); 5230 } 5231 #endif 5232 5233 UpdateMaximumCommitted(); 5234 5235 if (FLAG_print_cumulative_gc_stat) { 5236 PrintF("\n"); 5237 PrintF("gc_count=%d ", gc_count_); 5238 PrintF("mark_sweep_count=%d ", ms_count_); 5239 PrintF("max_gc_pause=%.1f ", get_max_gc_pause()); 5240 PrintF("total_gc_time=%.1f ", total_gc_time_ms_); 5241 PrintF("min_in_mutator=%.1f ", get_min_in_mutator()); 5242 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", get_max_alive_after_gc()); 5243 PrintF("total_marking_time=%.1f ", tracer()->cumulative_marking_duration()); 5244 PrintF("total_sweeping_time=%.1f ", 5245 tracer()->cumulative_sweeping_duration()); 5246 PrintF("\n\n"); 5247 } 5248 5249 if (FLAG_print_max_heap_committed) { 5250 PrintF("\n"); 5251 PrintF("maximum_committed_by_heap=%" V8_PTR_PREFIX "d ", 5252 MaximumCommittedMemory()); 5253 PrintF("maximum_committed_by_new_space=%" V8_PTR_PREFIX "d ", 5254 new_space_.MaximumCommittedMemory()); 5255 PrintF("maximum_committed_by_old_space=%" V8_PTR_PREFIX "d ", 5256 old_space_->MaximumCommittedMemory()); 5257 PrintF("maximum_committed_by_code_space=%" V8_PTR_PREFIX "d ", 5258 code_space_->MaximumCommittedMemory()); 5259 PrintF("maximum_committed_by_map_space=%" V8_PTR_PREFIX "d ", 5260 map_space_->MaximumCommittedMemory()); 5261 PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ", 5262 lo_space_->MaximumCommittedMemory()); 5263 PrintF("\n\n"); 5264 } 5265 5266 if (FLAG_verify_predictable) { 5267 PrintAlloctionsHash(); 5268 } 5269 5270 new_space()->RemoveInlineAllocationObserver(idle_scavenge_observer_); 5271 delete idle_scavenge_observer_; 5272 idle_scavenge_observer_ = nullptr; 5273 5274 delete scavenge_collector_; 5275 scavenge_collector_ = nullptr; 5276 5277 if (mark_compact_collector_ != nullptr) { 5278 mark_compact_collector_->TearDown(); 5279 delete mark_compact_collector_; 5280 mark_compact_collector_ = nullptr; 5281 } 5282 5283 delete incremental_marking_; 5284 incremental_marking_ = nullptr; 5285 5286 delete gc_idle_time_handler_; 5287 gc_idle_time_handler_ = nullptr; 5288 5289 if (memory_reducer_ != nullptr) { 5290 memory_reducer_->TearDown(); 5291 delete memory_reducer_; 5292 memory_reducer_ = nullptr; 5293 } 5294 5295 delete object_stats_; 5296 object_stats_ = nullptr; 5297 5298 delete scavenge_job_; 5299 scavenge_job_ = nullptr; 5300 5301 WaitUntilUnmappingOfFreeChunksCompleted(); 5302 5303 delete array_buffer_tracker_; 5304 array_buffer_tracker_ = nullptr; 5305 5306 isolate_->global_handles()->TearDown(); 5307 5308 external_string_table_.TearDown(); 5309 5310 delete tracer_; 5311 tracer_ = nullptr; 5312 5313 new_space_.TearDown(); 5314 5315 if (old_space_ != NULL) { 5316 delete old_space_; 5317 old_space_ = NULL; 5318 } 5319 5320 if (code_space_ != NULL) { 5321 delete code_space_; 5322 code_space_ = NULL; 5323 } 5324 5325 if (map_space_ != NULL) { 5326 delete map_space_; 5327 map_space_ = NULL; 5328 } 5329 5330 if (lo_space_ != NULL) { 5331 lo_space_->TearDown(); 5332 delete lo_space_; 5333 lo_space_ = NULL; 5334 } 5335 5336 store_buffer()->TearDown(); 5337 5338 isolate_->memory_allocator()->TearDown(); 5339 5340 StrongRootsList* next = NULL; 5341 for (StrongRootsList* list = strong_roots_list_; list; list = next) { 5342 next = list->next; 5343 delete list; 5344 } 5345 strong_roots_list_ = NULL; 5346 } 5347 5348 5349 void Heap::AddGCPrologueCallback(v8::Isolate::GCCallback callback, 5350 GCType gc_type, bool pass_isolate) { 5351 DCHECK(callback != NULL); 5352 GCCallbackPair pair(callback, gc_type, pass_isolate); 5353 DCHECK(!gc_prologue_callbacks_.Contains(pair)); 5354 return gc_prologue_callbacks_.Add(pair); 5355 } 5356 5357 5358 void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) { 5359 DCHECK(callback != NULL); 5360 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { 5361 if (gc_prologue_callbacks_[i].callback == callback) { 5362 gc_prologue_callbacks_.Remove(i); 5363 return; 5364 } 5365 } 5366 UNREACHABLE(); 5367 } 5368 5369 5370 void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallback callback, 5371 GCType gc_type, bool pass_isolate) { 5372 DCHECK(callback != NULL); 5373 GCCallbackPair pair(callback, gc_type, pass_isolate); 5374 DCHECK(!gc_epilogue_callbacks_.Contains(pair)); 5375 return gc_epilogue_callbacks_.Add(pair); 5376 } 5377 5378 5379 void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback) { 5380 DCHECK(callback != NULL); 5381 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { 5382 if (gc_epilogue_callbacks_[i].callback == callback) { 5383 gc_epilogue_callbacks_.Remove(i); 5384 return; 5385 } 5386 } 5387 UNREACHABLE(); 5388 } 5389 5390 5391 // TODO(ishell): Find a better place for this. 5392 void Heap::AddWeakObjectToCodeDependency(Handle<HeapObject> obj, 5393 Handle<DependentCode> dep) { 5394 DCHECK(!InNewSpace(*obj)); 5395 DCHECK(!InNewSpace(*dep)); 5396 Handle<WeakHashTable> table(weak_object_to_code_table(), isolate()); 5397 table = WeakHashTable::Put(table, obj, dep); 5398 if (*table != weak_object_to_code_table()) 5399 set_weak_object_to_code_table(*table); 5400 DCHECK_EQ(*dep, LookupWeakObjectToCodeDependency(obj)); 5401 } 5402 5403 5404 DependentCode* Heap::LookupWeakObjectToCodeDependency(Handle<HeapObject> obj) { 5405 Object* dep = weak_object_to_code_table()->Lookup(obj); 5406 if (dep->IsDependentCode()) return DependentCode::cast(dep); 5407 return DependentCode::cast(empty_fixed_array()); 5408 } 5409 5410 5411 void Heap::AddRetainedMap(Handle<Map> map) { 5412 Handle<WeakCell> cell = Map::WeakCellForMap(map); 5413 Handle<ArrayList> array(retained_maps(), isolate()); 5414 if (array->IsFull()) { 5415 CompactRetainedMaps(*array); 5416 } 5417 array = ArrayList::Add( 5418 array, cell, handle(Smi::FromInt(FLAG_retain_maps_for_n_gc), isolate()), 5419 ArrayList::kReloadLengthAfterAllocation); 5420 if (*array != retained_maps()) { 5421 set_retained_maps(*array); 5422 } 5423 } 5424 5425 5426 void Heap::CompactRetainedMaps(ArrayList* retained_maps) { 5427 DCHECK_EQ(retained_maps, this->retained_maps()); 5428 int length = retained_maps->Length(); 5429 int new_length = 0; 5430 int new_number_of_disposed_maps = 0; 5431 // This loop compacts the array by removing cleared weak cells. 5432 for (int i = 0; i < length; i += 2) { 5433 DCHECK(retained_maps->Get(i)->IsWeakCell()); 5434 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); 5435 Object* age = retained_maps->Get(i + 1); 5436 if (cell->cleared()) continue; 5437 if (i != new_length) { 5438 retained_maps->Set(new_length, cell); 5439 retained_maps->Set(new_length + 1, age); 5440 } 5441 if (i < number_of_disposed_maps_) { 5442 new_number_of_disposed_maps += 2; 5443 } 5444 new_length += 2; 5445 } 5446 number_of_disposed_maps_ = new_number_of_disposed_maps; 5447 Object* undefined = undefined_value(); 5448 for (int i = new_length; i < length; i++) { 5449 retained_maps->Clear(i, undefined); 5450 } 5451 if (new_length != length) retained_maps->SetLength(new_length); 5452 } 5453 5454 5455 void Heap::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { 5456 v8::internal::V8::FatalProcessOutOfMemory(location, take_snapshot); 5457 } 5458 5459 #ifdef DEBUG 5460 5461 class PrintHandleVisitor : public ObjectVisitor { 5462 public: 5463 void VisitPointers(Object** start, Object** end) override { 5464 for (Object** p = start; p < end; p++) 5465 PrintF(" handle %p to %p\n", reinterpret_cast<void*>(p), 5466 reinterpret_cast<void*>(*p)); 5467 } 5468 }; 5469 5470 5471 void Heap::PrintHandles() { 5472 PrintF("Handles:\n"); 5473 PrintHandleVisitor v; 5474 isolate_->handle_scope_implementer()->Iterate(&v); 5475 } 5476 5477 #endif 5478 5479 class CheckHandleCountVisitor : public ObjectVisitor { 5480 public: 5481 CheckHandleCountVisitor() : handle_count_(0) {} 5482 ~CheckHandleCountVisitor() override { 5483 CHECK(handle_count_ < HandleScope::kCheckHandleThreshold); 5484 } 5485 void VisitPointers(Object** start, Object** end) override { 5486 handle_count_ += end - start; 5487 } 5488 5489 private: 5490 ptrdiff_t handle_count_; 5491 }; 5492 5493 5494 void Heap::CheckHandleCount() { 5495 CheckHandleCountVisitor v; 5496 isolate_->handle_scope_implementer()->Iterate(&v); 5497 } 5498 5499 5500 Space* AllSpaces::next() { 5501 switch (counter_++) { 5502 case NEW_SPACE: 5503 return heap_->new_space(); 5504 case OLD_SPACE: 5505 return heap_->old_space(); 5506 case CODE_SPACE: 5507 return heap_->code_space(); 5508 case MAP_SPACE: 5509 return heap_->map_space(); 5510 case LO_SPACE: 5511 return heap_->lo_space(); 5512 default: 5513 return NULL; 5514 } 5515 } 5516 5517 5518 PagedSpace* PagedSpaces::next() { 5519 switch (counter_++) { 5520 case OLD_SPACE: 5521 return heap_->old_space(); 5522 case CODE_SPACE: 5523 return heap_->code_space(); 5524 case MAP_SPACE: 5525 return heap_->map_space(); 5526 default: 5527 return NULL; 5528 } 5529 } 5530 5531 5532 OldSpace* OldSpaces::next() { 5533 switch (counter_++) { 5534 case OLD_SPACE: 5535 return heap_->old_space(); 5536 case CODE_SPACE: 5537 return heap_->code_space(); 5538 default: 5539 return NULL; 5540 } 5541 } 5542 5543 5544 SpaceIterator::SpaceIterator(Heap* heap) 5545 : heap_(heap), current_space_(FIRST_SPACE), iterator_(NULL) {} 5546 5547 5548 SpaceIterator::~SpaceIterator() { 5549 // Delete active iterator if any. 5550 delete iterator_; 5551 } 5552 5553 5554 bool SpaceIterator::has_next() { 5555 // Iterate until no more spaces. 5556 return current_space_ != LAST_SPACE; 5557 } 5558 5559 5560 ObjectIterator* SpaceIterator::next() { 5561 if (iterator_ != NULL) { 5562 delete iterator_; 5563 iterator_ = NULL; 5564 // Move to the next space 5565 current_space_++; 5566 if (current_space_ > LAST_SPACE) { 5567 return NULL; 5568 } 5569 } 5570 5571 // Return iterator for the new current space. 5572 return CreateIterator(); 5573 } 5574 5575 5576 // Create an iterator for the space to iterate. 5577 ObjectIterator* SpaceIterator::CreateIterator() { 5578 DCHECK(iterator_ == NULL); 5579 5580 switch (current_space_) { 5581 case NEW_SPACE: 5582 iterator_ = new SemiSpaceIterator(heap_->new_space()); 5583 break; 5584 case OLD_SPACE: 5585 iterator_ = new HeapObjectIterator(heap_->old_space()); 5586 break; 5587 case CODE_SPACE: 5588 iterator_ = new HeapObjectIterator(heap_->code_space()); 5589 break; 5590 case MAP_SPACE: 5591 iterator_ = new HeapObjectIterator(heap_->map_space()); 5592 break; 5593 case LO_SPACE: 5594 iterator_ = new LargeObjectIterator(heap_->lo_space()); 5595 break; 5596 } 5597 5598 // Return the newly allocated iterator; 5599 DCHECK(iterator_ != NULL); 5600 return iterator_; 5601 } 5602 5603 5604 class HeapObjectsFilter { 5605 public: 5606 virtual ~HeapObjectsFilter() {} 5607 virtual bool SkipObject(HeapObject* object) = 0; 5608 }; 5609 5610 5611 class UnreachableObjectsFilter : public HeapObjectsFilter { 5612 public: 5613 explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) { 5614 MarkReachableObjects(); 5615 } 5616 5617 ~UnreachableObjectsFilter() { 5618 heap_->mark_compact_collector()->ClearMarkbits(); 5619 } 5620 5621 bool SkipObject(HeapObject* object) { 5622 if (object->IsFiller()) return true; 5623 MarkBit mark_bit = Marking::MarkBitFrom(object); 5624 return Marking::IsWhite(mark_bit); 5625 } 5626 5627 private: 5628 class MarkingVisitor : public ObjectVisitor { 5629 public: 5630 MarkingVisitor() : marking_stack_(10) {} 5631 5632 void VisitPointers(Object** start, Object** end) override { 5633 for (Object** p = start; p < end; p++) { 5634 if (!(*p)->IsHeapObject()) continue; 5635 HeapObject* obj = HeapObject::cast(*p); 5636 MarkBit mark_bit = Marking::MarkBitFrom(obj); 5637 if (Marking::IsWhite(mark_bit)) { 5638 Marking::WhiteToBlack(mark_bit); 5639 marking_stack_.Add(obj); 5640 } 5641 } 5642 } 5643 5644 void TransitiveClosure() { 5645 while (!marking_stack_.is_empty()) { 5646 HeapObject* obj = marking_stack_.RemoveLast(); 5647 obj->Iterate(this); 5648 } 5649 } 5650 5651 private: 5652 List<HeapObject*> marking_stack_; 5653 }; 5654 5655 void MarkReachableObjects() { 5656 MarkingVisitor visitor; 5657 heap_->IterateRoots(&visitor, VISIT_ALL); 5658 visitor.TransitiveClosure(); 5659 } 5660 5661 Heap* heap_; 5662 DisallowHeapAllocation no_allocation_; 5663 }; 5664 5665 5666 HeapIterator::HeapIterator(Heap* heap, 5667 HeapIterator::HeapObjectsFiltering filtering) 5668 : make_heap_iterable_helper_(heap), 5669 no_heap_allocation_(), 5670 heap_(heap), 5671 filtering_(filtering), 5672 filter_(nullptr), 5673 space_iterator_(nullptr), 5674 object_iterator_(nullptr) { 5675 heap_->heap_iterator_start(); 5676 // Start the iteration. 5677 space_iterator_ = new SpaceIterator(heap_); 5678 switch (filtering_) { 5679 case kFilterUnreachable: 5680 filter_ = new UnreachableObjectsFilter(heap_); 5681 break; 5682 default: 5683 break; 5684 } 5685 object_iterator_ = space_iterator_->next(); 5686 } 5687 5688 5689 HeapIterator::~HeapIterator() { 5690 heap_->heap_iterator_end(); 5691 #ifdef DEBUG 5692 // Assert that in filtering mode we have iterated through all 5693 // objects. Otherwise, heap will be left in an inconsistent state. 5694 if (filtering_ != kNoFiltering) { 5695 DCHECK(object_iterator_ == nullptr); 5696 } 5697 #endif 5698 // Make sure the last iterator is deallocated. 5699 delete object_iterator_; 5700 delete space_iterator_; 5701 delete filter_; 5702 } 5703 5704 5705 HeapObject* HeapIterator::next() { 5706 if (filter_ == nullptr) return NextObject(); 5707 5708 HeapObject* obj = NextObject(); 5709 while ((obj != nullptr) && (filter_->SkipObject(obj))) obj = NextObject(); 5710 return obj; 5711 } 5712 5713 5714 HeapObject* HeapIterator::NextObject() { 5715 // No iterator means we are done. 5716 if (object_iterator_ == nullptr) return nullptr; 5717 5718 if (HeapObject* obj = object_iterator_->next_object()) { 5719 // If the current iterator has more objects we are fine. 5720 return obj; 5721 } else { 5722 // Go though the spaces looking for one that has objects. 5723 while (space_iterator_->has_next()) { 5724 object_iterator_ = space_iterator_->next(); 5725 if (HeapObject* obj = object_iterator_->next_object()) { 5726 return obj; 5727 } 5728 } 5729 } 5730 // Done with the last space. 5731 object_iterator_ = nullptr; 5732 return nullptr; 5733 } 5734 5735 5736 #ifdef DEBUG 5737 5738 Object* const PathTracer::kAnyGlobalObject = NULL; 5739 5740 class PathTracer::MarkVisitor : public ObjectVisitor { 5741 public: 5742 explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {} 5743 5744 void VisitPointers(Object** start, Object** end) override { 5745 // Scan all HeapObject pointers in [start, end) 5746 for (Object** p = start; !tracer_->found() && (p < end); p++) { 5747 if ((*p)->IsHeapObject()) tracer_->MarkRecursively(p, this); 5748 } 5749 } 5750 5751 private: 5752 PathTracer* tracer_; 5753 }; 5754 5755 5756 class PathTracer::UnmarkVisitor : public ObjectVisitor { 5757 public: 5758 explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {} 5759 5760 void VisitPointers(Object** start, Object** end) override { 5761 // Scan all HeapObject pointers in [start, end) 5762 for (Object** p = start; p < end; p++) { 5763 if ((*p)->IsHeapObject()) tracer_->UnmarkRecursively(p, this); 5764 } 5765 } 5766 5767 private: 5768 PathTracer* tracer_; 5769 }; 5770 5771 5772 void PathTracer::VisitPointers(Object** start, Object** end) { 5773 bool done = ((what_to_find_ == FIND_FIRST) && found_target_); 5774 // Visit all HeapObject pointers in [start, end) 5775 for (Object** p = start; !done && (p < end); p++) { 5776 if ((*p)->IsHeapObject()) { 5777 TracePathFrom(p); 5778 done = ((what_to_find_ == FIND_FIRST) && found_target_); 5779 } 5780 } 5781 } 5782 5783 5784 void PathTracer::Reset() { 5785 found_target_ = false; 5786 object_stack_.Clear(); 5787 } 5788 5789 5790 void PathTracer::TracePathFrom(Object** root) { 5791 DCHECK((search_target_ == kAnyGlobalObject) || 5792 search_target_->IsHeapObject()); 5793 found_target_in_trace_ = false; 5794 Reset(); 5795 5796 MarkVisitor mark_visitor(this); 5797 MarkRecursively(root, &mark_visitor); 5798 5799 UnmarkVisitor unmark_visitor(this); 5800 UnmarkRecursively(root, &unmark_visitor); 5801 5802 ProcessResults(); 5803 } 5804 5805 5806 static bool SafeIsNativeContext(HeapObject* obj) { 5807 return obj->map() == obj->GetHeap()->root(Heap::kNativeContextMapRootIndex); 5808 } 5809 5810 5811 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) { 5812 if (!(*p)->IsHeapObject()) return; 5813 5814 HeapObject* obj = HeapObject::cast(*p); 5815 5816 MapWord map_word = obj->map_word(); 5817 if (!map_word.ToMap()->IsHeapObject()) return; // visited before 5818 5819 if (found_target_in_trace_) return; // stop if target found 5820 object_stack_.Add(obj); 5821 if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) || 5822 (obj == search_target_)) { 5823 found_target_in_trace_ = true; 5824 found_target_ = true; 5825 return; 5826 } 5827 5828 bool is_native_context = SafeIsNativeContext(obj); 5829 5830 // not visited yet 5831 Map* map = Map::cast(map_word.ToMap()); 5832 5833 MapWord marked_map_word = 5834 MapWord::FromRawValue(obj->map_word().ToRawValue() + kMarkTag); 5835 obj->set_map_word(marked_map_word); 5836 5837 // Scan the object body. 5838 if (is_native_context && (visit_mode_ == VISIT_ONLY_STRONG)) { 5839 // This is specialized to scan Context's properly. 5840 Object** start = 5841 reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize); 5842 Object** end = 5843 reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize + 5844 Context::FIRST_WEAK_SLOT * kPointerSize); 5845 mark_visitor->VisitPointers(start, end); 5846 } else { 5847 obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), mark_visitor); 5848 } 5849 5850 // Scan the map after the body because the body is a lot more interesting 5851 // when doing leak detection. 5852 MarkRecursively(reinterpret_cast<Object**>(&map), mark_visitor); 5853 5854 if (!found_target_in_trace_) { // don't pop if found the target 5855 object_stack_.RemoveLast(); 5856 } 5857 } 5858 5859 5860 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) { 5861 if (!(*p)->IsHeapObject()) return; 5862 5863 HeapObject* obj = HeapObject::cast(*p); 5864 5865 MapWord map_word = obj->map_word(); 5866 if (map_word.ToMap()->IsHeapObject()) return; // unmarked already 5867 5868 MapWord unmarked_map_word = 5869 MapWord::FromRawValue(map_word.ToRawValue() - kMarkTag); 5870 obj->set_map_word(unmarked_map_word); 5871 5872 Map* map = Map::cast(unmarked_map_word.ToMap()); 5873 5874 UnmarkRecursively(reinterpret_cast<Object**>(&map), unmark_visitor); 5875 5876 obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), unmark_visitor); 5877 } 5878 5879 5880 void PathTracer::ProcessResults() { 5881 if (found_target_) { 5882 OFStream os(stdout); 5883 os << "=====================================\n" 5884 << "==== Path to object ====\n" 5885 << "=====================================\n\n"; 5886 5887 DCHECK(!object_stack_.is_empty()); 5888 for (int i = 0; i < object_stack_.length(); i++) { 5889 if (i > 0) os << "\n |\n |\n V\n\n"; 5890 object_stack_[i]->Print(os); 5891 } 5892 os << "=====================================\n"; 5893 } 5894 } 5895 5896 5897 // Triggers a depth-first traversal of reachable objects from one 5898 // given root object and finds a path to a specific heap object and 5899 // prints it. 5900 void Heap::TracePathToObjectFrom(Object* target, Object* root) { 5901 PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL); 5902 tracer.VisitPointer(&root); 5903 } 5904 5905 5906 // Triggers a depth-first traversal of reachable objects from roots 5907 // and finds a path to a specific heap object and prints it. 5908 void Heap::TracePathToObject(Object* target) { 5909 PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL); 5910 IterateRoots(&tracer, VISIT_ONLY_STRONG); 5911 } 5912 5913 5914 // Triggers a depth-first traversal of reachable objects from roots 5915 // and finds a path to any global object and prints it. Useful for 5916 // determining the source for leaks of global objects. 5917 void Heap::TracePathToGlobal() { 5918 PathTracer tracer(PathTracer::kAnyGlobalObject, PathTracer::FIND_ALL, 5919 VISIT_ALL); 5920 IterateRoots(&tracer, VISIT_ONLY_STRONG); 5921 } 5922 #endif 5923 5924 5925 void Heap::UpdateCumulativeGCStatistics(double duration, 5926 double spent_in_mutator, 5927 double marking_time) { 5928 if (FLAG_print_cumulative_gc_stat) { 5929 total_gc_time_ms_ += duration; 5930 max_gc_pause_ = Max(max_gc_pause_, duration); 5931 max_alive_after_gc_ = Max(max_alive_after_gc_, SizeOfObjects()); 5932 min_in_mutator_ = Min(min_in_mutator_, spent_in_mutator); 5933 } else if (FLAG_trace_gc_verbose) { 5934 total_gc_time_ms_ += duration; 5935 } 5936 5937 marking_time_ += marking_time; 5938 } 5939 5940 5941 int KeyedLookupCache::Hash(Handle<Map> map, Handle<Name> name) { 5942 DisallowHeapAllocation no_gc; 5943 // Uses only lower 32 bits if pointers are larger. 5944 uintptr_t addr_hash = 5945 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*map)) >> kMapHashShift; 5946 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); 5947 } 5948 5949 5950 int KeyedLookupCache::Lookup(Handle<Map> map, Handle<Name> name) { 5951 DisallowHeapAllocation no_gc; 5952 int index = (Hash(map, name) & kHashMask); 5953 for (int i = 0; i < kEntriesPerBucket; i++) { 5954 Key& key = keys_[index + i]; 5955 if ((key.map == *map) && key.name->Equals(*name)) { 5956 return field_offsets_[index + i]; 5957 } 5958 } 5959 return kNotFound; 5960 } 5961 5962 5963 void KeyedLookupCache::Update(Handle<Map> map, Handle<Name> name, 5964 int field_offset) { 5965 DisallowHeapAllocation no_gc; 5966 if (!name->IsUniqueName()) { 5967 if (!StringTable::InternalizeStringIfExists( 5968 name->GetIsolate(), Handle<String>::cast(name)).ToHandle(&name)) { 5969 return; 5970 } 5971 } 5972 // This cache is cleared only between mark compact passes, so we expect the 5973 // cache to only contain old space names. 5974 DCHECK(!map->GetIsolate()->heap()->InNewSpace(*name)); 5975 5976 int index = (Hash(map, name) & kHashMask); 5977 // After a GC there will be free slots, so we use them in order (this may 5978 // help to get the most frequently used one in position 0). 5979 for (int i = 0; i < kEntriesPerBucket; i++) { 5980 Key& key = keys_[index]; 5981 Object* free_entry_indicator = NULL; 5982 if (key.map == free_entry_indicator) { 5983 key.map = *map; 5984 key.name = *name; 5985 field_offsets_[index + i] = field_offset; 5986 return; 5987 } 5988 } 5989 // No free entry found in this bucket, so we move them all down one and 5990 // put the new entry at position zero. 5991 for (int i = kEntriesPerBucket - 1; i > 0; i--) { 5992 Key& key = keys_[index + i]; 5993 Key& key2 = keys_[index + i - 1]; 5994 key = key2; 5995 field_offsets_[index + i] = field_offsets_[index + i - 1]; 5996 } 5997 5998 // Write the new first entry. 5999 Key& key = keys_[index]; 6000 key.map = *map; 6001 key.name = *name; 6002 field_offsets_[index] = field_offset; 6003 } 6004 6005 6006 void KeyedLookupCache::Clear() { 6007 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; 6008 } 6009 6010 6011 void DescriptorLookupCache::Clear() { 6012 for (int index = 0; index < kLength; index++) keys_[index].source = NULL; 6013 } 6014 6015 6016 void Heap::ExternalStringTable::CleanUp() { 6017 int last = 0; 6018 for (int i = 0; i < new_space_strings_.length(); ++i) { 6019 if (new_space_strings_[i] == heap_->the_hole_value()) { 6020 continue; 6021 } 6022 DCHECK(new_space_strings_[i]->IsExternalString()); 6023 if (heap_->InNewSpace(new_space_strings_[i])) { 6024 new_space_strings_[last++] = new_space_strings_[i]; 6025 } else { 6026 old_space_strings_.Add(new_space_strings_[i]); 6027 } 6028 } 6029 new_space_strings_.Rewind(last); 6030 new_space_strings_.Trim(); 6031 6032 last = 0; 6033 for (int i = 0; i < old_space_strings_.length(); ++i) { 6034 if (old_space_strings_[i] == heap_->the_hole_value()) { 6035 continue; 6036 } 6037 DCHECK(old_space_strings_[i]->IsExternalString()); 6038 DCHECK(!heap_->InNewSpace(old_space_strings_[i])); 6039 old_space_strings_[last++] = old_space_strings_[i]; 6040 } 6041 old_space_strings_.Rewind(last); 6042 old_space_strings_.Trim(); 6043 #ifdef VERIFY_HEAP 6044 if (FLAG_verify_heap) { 6045 Verify(); 6046 } 6047 #endif 6048 } 6049 6050 6051 void Heap::ExternalStringTable::TearDown() { 6052 for (int i = 0; i < new_space_strings_.length(); ++i) { 6053 heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i])); 6054 } 6055 new_space_strings_.Free(); 6056 for (int i = 0; i < old_space_strings_.length(); ++i) { 6057 heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i])); 6058 } 6059 old_space_strings_.Free(); 6060 } 6061 6062 6063 class Heap::UnmapFreeMemoryTask : public v8::Task { 6064 public: 6065 UnmapFreeMemoryTask(Heap* heap, MemoryChunk* head) 6066 : heap_(heap), head_(head) {} 6067 virtual ~UnmapFreeMemoryTask() {} 6068 6069 private: 6070 // v8::Task overrides. 6071 void Run() override { 6072 heap_->FreeQueuedChunks(head_); 6073 heap_->pending_unmapping_tasks_semaphore_.Signal(); 6074 } 6075 6076 Heap* heap_; 6077 MemoryChunk* head_; 6078 6079 DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask); 6080 }; 6081 6082 6083 void Heap::WaitUntilUnmappingOfFreeChunksCompleted() { 6084 while (concurrent_unmapping_tasks_active_ > 0) { 6085 pending_unmapping_tasks_semaphore_.Wait(); 6086 concurrent_unmapping_tasks_active_--; 6087 } 6088 } 6089 6090 6091 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { 6092 // PreFree logically frees the memory chunk. However, the actual freeing 6093 // will happen on a separate thread sometime later. 6094 isolate_->memory_allocator()->PreFreeMemory(chunk); 6095 6096 // The chunks added to this queue will be freed by a concurrent thread. 6097 chunk->set_next_chunk(chunks_queued_for_free_); 6098 chunks_queued_for_free_ = chunk; 6099 } 6100 6101 6102 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { 6103 if (chunks_queued_for_free_ == NULL) return; 6104 MemoryChunk* next; 6105 MemoryChunk* chunk; 6106 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { 6107 next = chunk->next_chunk(); 6108 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); 6109 } 6110 store_buffer()->Compact(); 6111 store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); 6112 } 6113 6114 6115 void Heap::FreeQueuedChunks() { 6116 if (chunks_queued_for_free_ != NULL) { 6117 if (FLAG_concurrent_sweeping) { 6118 V8::GetCurrentPlatform()->CallOnBackgroundThread( 6119 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), 6120 v8::Platform::kShortRunningTask); 6121 } else { 6122 FreeQueuedChunks(chunks_queued_for_free_); 6123 pending_unmapping_tasks_semaphore_.Signal(); 6124 } 6125 chunks_queued_for_free_ = NULL; 6126 } else { 6127 // If we do not have anything to unmap, we just signal the semaphore 6128 // that we are done. 6129 pending_unmapping_tasks_semaphore_.Signal(); 6130 } 6131 concurrent_unmapping_tasks_active_++; 6132 } 6133 6134 6135 void Heap::FreeQueuedChunks(MemoryChunk* list_head) { 6136 MemoryChunk* next; 6137 MemoryChunk* chunk; 6138 for (chunk = list_head; chunk != NULL; chunk = next) { 6139 next = chunk->next_chunk(); 6140 isolate_->memory_allocator()->PerformFreeMemory(chunk); 6141 } 6142 } 6143 6144 6145 void Heap::RememberUnmappedPage(Address page, bool compacted) { 6146 uintptr_t p = reinterpret_cast<uintptr_t>(page); 6147 // Tag the page pointer to make it findable in the dump file. 6148 if (compacted) { 6149 p ^= 0xc1ead & (Page::kPageSize - 1); // Cleared. 6150 } else { 6151 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. 6152 } 6153 remembered_unmapped_pages_[remembered_unmapped_pages_index_] = 6154 reinterpret_cast<Address>(p); 6155 remembered_unmapped_pages_index_++; 6156 remembered_unmapped_pages_index_ %= kRememberedUnmappedPages; 6157 } 6158 6159 6160 void Heap::RegisterStrongRoots(Object** start, Object** end) { 6161 StrongRootsList* list = new StrongRootsList(); 6162 list->next = strong_roots_list_; 6163 list->start = start; 6164 list->end = end; 6165 strong_roots_list_ = list; 6166 } 6167 6168 6169 void Heap::UnregisterStrongRoots(Object** start) { 6170 StrongRootsList* prev = NULL; 6171 StrongRootsList* list = strong_roots_list_; 6172 while (list != nullptr) { 6173 StrongRootsList* next = list->next; 6174 if (list->start == start) { 6175 if (prev) { 6176 prev->next = next; 6177 } else { 6178 strong_roots_list_ = next; 6179 } 6180 delete list; 6181 } else { 6182 prev = list; 6183 } 6184 list = next; 6185 } 6186 } 6187 6188 6189 size_t Heap::NumberOfTrackedHeapObjectTypes() { 6190 return ObjectStats::OBJECT_STATS_COUNT; 6191 } 6192 6193 6194 size_t Heap::ObjectCountAtLastGC(size_t index) { 6195 if (index >= ObjectStats::OBJECT_STATS_COUNT) return 0; 6196 return object_stats_->object_count_last_gc(index); 6197 } 6198 6199 6200 size_t Heap::ObjectSizeAtLastGC(size_t index) { 6201 if (index >= ObjectStats::OBJECT_STATS_COUNT) return 0; 6202 return object_stats_->object_size_last_gc(index); 6203 } 6204 6205 6206 bool Heap::GetObjectTypeName(size_t index, const char** object_type, 6207 const char** object_sub_type) { 6208 if (index >= ObjectStats::OBJECT_STATS_COUNT) return false; 6209 6210 switch (static_cast<int>(index)) { 6211 #define COMPARE_AND_RETURN_NAME(name) \ 6212 case name: \ 6213 *object_type = #name; \ 6214 *object_sub_type = ""; \ 6215 return true; 6216 INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME) 6217 #undef COMPARE_AND_RETURN_NAME 6218 #define COMPARE_AND_RETURN_NAME(name) \ 6219 case ObjectStats::FIRST_CODE_KIND_SUB_TYPE + Code::name: \ 6220 *object_type = "CODE_TYPE"; \ 6221 *object_sub_type = "CODE_KIND/" #name; \ 6222 return true; 6223 CODE_KIND_LIST(COMPARE_AND_RETURN_NAME) 6224 #undef COMPARE_AND_RETURN_NAME 6225 #define COMPARE_AND_RETURN_NAME(name) \ 6226 case ObjectStats::FIRST_FIXED_ARRAY_SUB_TYPE + name: \ 6227 *object_type = "FIXED_ARRAY_TYPE"; \ 6228 *object_sub_type = #name; \ 6229 return true; 6230 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COMPARE_AND_RETURN_NAME) 6231 #undef COMPARE_AND_RETURN_NAME 6232 #define COMPARE_AND_RETURN_NAME(name) \ 6233 case ObjectStats::FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - \ 6234 Code::kFirstCodeAge: \ 6235 *object_type = "CODE_TYPE"; \ 6236 *object_sub_type = "CODE_AGE/" #name; \ 6237 return true; 6238 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) 6239 #undef COMPARE_AND_RETURN_NAME 6240 } 6241 return false; 6242 } 6243 6244 6245 // static 6246 int Heap::GetStaticVisitorIdForMap(Map* map) { 6247 return StaticVisitorBase::GetVisitorId(map); 6248 } 6249 6250 } // namespace internal 6251 } // namespace v8 6252