| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/ast/context-slot-cache.h" | 9 #include "src/ast/context-slot-cache.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 set_native_contexts_list(NULL); | 172 set_native_contexts_list(NULL); |
| 173 set_allocation_sites_list(Smi::kZero); | 173 set_allocation_sites_list(Smi::kZero); |
| 174 set_encountered_weak_collections(Smi::kZero); | 174 set_encountered_weak_collections(Smi::kZero); |
| 175 set_encountered_weak_cells(Smi::kZero); | 175 set_encountered_weak_cells(Smi::kZero); |
| 176 set_encountered_transition_arrays(Smi::kZero); | 176 set_encountered_transition_arrays(Smi::kZero); |
| 177 // Put a dummy entry in the remembered pages so we can find the list the | 177 // Put a dummy entry in the remembered pages so we can find the list the |
| 178 // minidump even if there are no real unmapped pages. | 178 // minidump even if there are no real unmapped pages. |
| 179 RememberUnmappedPage(NULL, false); | 179 RememberUnmappedPage(NULL, false); |
| 180 } | 180 } |
| 181 | 181 |
| 182 | 182 size_t Heap::Capacity() { |
| 183 intptr_t Heap::Capacity() { | |
| 184 if (!HasBeenSetUp()) return 0; | 183 if (!HasBeenSetUp()) return 0; |
| 185 | 184 |
| 186 return new_space_->Capacity() + OldGenerationCapacity(); | 185 return new_space_->Capacity() + OldGenerationCapacity(); |
| 187 } | 186 } |
| 188 | 187 |
| 189 intptr_t Heap::OldGenerationCapacity() { | 188 size_t Heap::OldGenerationCapacity() { |
| 190 if (!HasBeenSetUp()) return 0; | 189 if (!HasBeenSetUp()) return 0; |
| 191 | 190 |
| 192 return old_space_->Capacity() + code_space_->Capacity() + | 191 return old_space_->Capacity() + code_space_->Capacity() + |
| 193 map_space_->Capacity() + lo_space_->SizeOfObjects(); | 192 map_space_->Capacity() + lo_space_->SizeOfObjects(); |
| 194 } | 193 } |
| 195 | 194 |
| 196 size_t Heap::CommittedOldGenerationMemory() { | 195 size_t Heap::CommittedOldGenerationMemory() { |
| 197 if (!HasBeenSetUp()) return 0; | 196 if (!HasBeenSetUp()) return 0; |
| 198 | 197 |
| 199 return old_space_->CommittedMemory() + code_space_->CommittedMemory() + | 198 return old_space_->CommittedMemory() + code_space_->CommittedMemory() + |
| (...skipping 26 matching lines...) Expand all Loading... |
| 226 | 225 |
| 227 void Heap::UpdateMaximumCommitted() { | 226 void Heap::UpdateMaximumCommitted() { |
| 228 if (!HasBeenSetUp()) return; | 227 if (!HasBeenSetUp()) return; |
| 229 | 228 |
| 230 const size_t current_committed_memory = CommittedMemory(); | 229 const size_t current_committed_memory = CommittedMemory(); |
| 231 if (current_committed_memory > maximum_committed_) { | 230 if (current_committed_memory > maximum_committed_) { |
| 232 maximum_committed_ = current_committed_memory; | 231 maximum_committed_ = current_committed_memory; |
| 233 } | 232 } |
| 234 } | 233 } |
| 235 | 234 |
| 236 | 235 size_t Heap::Available() { |
| 237 intptr_t Heap::Available() { | |
| 238 if (!HasBeenSetUp()) return 0; | 236 if (!HasBeenSetUp()) return 0; |
| 239 | 237 |
| 240 intptr_t total = 0; | 238 size_t total = 0; |
| 241 AllSpaces spaces(this); | 239 AllSpaces spaces(this); |
| 242 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { | 240 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
| 243 total += space->Available(); | 241 total += space->Available(); |
| 244 } | 242 } |
| 245 return total; | 243 return total; |
| 246 } | 244 } |
| 247 | 245 |
| 248 | 246 |
| 249 bool Heap::HasBeenSetUp() { | 247 bool Heap::HasBeenSetUp() { |
| 250 return old_space_ != NULL && code_space_ != NULL && map_space_ != NULL && | 248 return old_space_ != NULL && code_space_ != NULL && map_space_ != NULL && |
| (...skipping 17 matching lines...) Expand all Loading... |
| 268 | 266 |
| 269 // Is there enough space left in OLD to guarantee that a scavenge can | 267 // Is there enough space left in OLD to guarantee that a scavenge can |
| 270 // succeed? | 268 // succeed? |
| 271 // | 269 // |
| 272 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available | 270 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available |
| 273 // for object promotion. It counts only the bytes that the memory | 271 // for object promotion. It counts only the bytes that the memory |
| 274 // allocator has not yet allocated from the OS and assigned to any space, | 272 // allocator has not yet allocated from the OS and assigned to any space, |
| 275 // and does not count available bytes already in the old space or code | 273 // and does not count available bytes already in the old space or code |
| 276 // space. Undercounting is safe---we may get an unrequested full GC when | 274 // space. Undercounting is safe---we may get an unrequested full GC when |
| 277 // a scavenge would have succeeded. | 275 // a scavenge would have succeeded. |
| 278 if (static_cast<intptr_t>(memory_allocator()->MaxAvailable()) <= | 276 if (memory_allocator()->MaxAvailable() <= new_space_->Size()) { |
| 279 new_space_->Size()) { | |
| 280 isolate_->counters() | 277 isolate_->counters() |
| 281 ->gc_compactor_caused_by_oldspace_exhaustion() | 278 ->gc_compactor_caused_by_oldspace_exhaustion() |
| 282 ->Increment(); | 279 ->Increment(); |
| 283 *reason = "scavenge might not succeed"; | 280 *reason = "scavenge might not succeed"; |
| 284 return MARK_COMPACTOR; | 281 return MARK_COMPACTOR; |
| 285 } | 282 } |
| 286 | 283 |
| 287 // Default | 284 // Default |
| 288 *reason = NULL; | 285 *reason = NULL; |
| 289 return YoungGenerationCollector(); | 286 return YoungGenerationCollector(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 309 new_space_->CollectStatistics(); | 306 new_space_->CollectStatistics(); |
| 310 new_space_->ReportStatistics(); | 307 new_space_->ReportStatistics(); |
| 311 new_space_->ClearHistograms(); | 308 new_space_->ClearHistograms(); |
| 312 } | 309 } |
| 313 #endif // DEBUG | 310 #endif // DEBUG |
| 314 } | 311 } |
| 315 | 312 |
| 316 | 313 |
| 317 void Heap::PrintShortHeapStatistics() { | 314 void Heap::PrintShortHeapStatistics() { |
| 318 if (!FLAG_trace_gc_verbose) return; | 315 if (!FLAG_trace_gc_verbose) return; |
| 319 PrintIsolate(isolate_, | 316 PrintIsolate(isolate_, "Memory allocator, used: %6" PRIuS |
| 320 "Memory allocator, used: %6zu KB," | 317 " KB," |
| 321 " available: %6zu KB\n", | 318 " available: %6" PRIuS " KB\n", |
| 322 memory_allocator()->Size() / KB, | 319 memory_allocator()->Size() / KB, |
| 323 memory_allocator()->Available() / KB); | 320 memory_allocator()->Available() / KB); |
| 324 PrintIsolate(isolate_, "New space, used: %6" V8PRIdPTR | 321 PrintIsolate(isolate_, "New space, used: %6" PRIuS |
| 325 " KB" | 322 " KB" |
| 326 ", available: %6" V8PRIdPTR | 323 ", available: %6" PRIuS |
| 327 " KB" | 324 " KB" |
| 328 ", committed: %6zu KB\n", | 325 ", committed: %6" PRIuS " KB\n", |
| 329 new_space_->Size() / KB, new_space_->Available() / KB, | 326 new_space_->Size() / KB, new_space_->Available() / KB, |
| 330 new_space_->CommittedMemory() / KB); | 327 new_space_->CommittedMemory() / KB); |
| 331 PrintIsolate(isolate_, "Old space, used: %6" V8PRIdPTR | 328 PrintIsolate(isolate_, "Old space, used: %6" PRIuS |
| 332 " KB" | 329 " KB" |
| 333 ", available: %6" V8PRIdPTR | 330 ", available: %6" PRIuS |
| 334 " KB" | 331 " KB" |
| 335 ", committed: %6zu KB\n", | 332 ", committed: %6" PRIuS " KB\n", |
| 336 old_space_->SizeOfObjects() / KB, old_space_->Available() / KB, | 333 old_space_->SizeOfObjects() / KB, old_space_->Available() / KB, |
| 337 old_space_->CommittedMemory() / KB); | 334 old_space_->CommittedMemory() / KB); |
| 338 PrintIsolate(isolate_, "Code space, used: %6" V8PRIdPTR | 335 PrintIsolate(isolate_, "Code space, used: %6" PRIuS |
| 339 " KB" | 336 " KB" |
| 340 ", available: %6" V8PRIdPTR | 337 ", available: %6" PRIuS |
| 341 " KB" | 338 " KB" |
| 342 ", committed: %6zu KB\n", | 339 ", committed: %6" PRIuS "KB\n", |
| 343 code_space_->SizeOfObjects() / KB, code_space_->Available() / KB, | 340 code_space_->SizeOfObjects() / KB, code_space_->Available() / KB, |
| 344 code_space_->CommittedMemory() / KB); | 341 code_space_->CommittedMemory() / KB); |
| 345 PrintIsolate(isolate_, "Map space, used: %6" V8PRIdPTR | 342 PrintIsolate(isolate_, "Map space, used: %6" PRIuS |
| 346 " KB" | 343 " KB" |
| 347 ", available: %6" V8PRIdPTR | 344 ", available: %6" PRIuS |
| 348 " KB" | 345 " KB" |
| 349 ", committed: %6zu KB\n", | 346 ", committed: %6" PRIuS " KB\n", |
| 350 map_space_->SizeOfObjects() / KB, map_space_->Available() / KB, | 347 map_space_->SizeOfObjects() / KB, map_space_->Available() / KB, |
| 351 map_space_->CommittedMemory() / KB); | 348 map_space_->CommittedMemory() / KB); |
| 352 PrintIsolate(isolate_, "Large object space, used: %6" V8PRIdPTR | 349 PrintIsolate(isolate_, "Large object space, used: %6" PRIuS |
| 353 " KB" | 350 " KB" |
| 354 ", available: %6" V8PRIdPTR | 351 ", available: %6" PRIuS |
| 355 " KB" | 352 " KB" |
| 356 ", committed: %6zu KB\n", | 353 ", committed: %6" PRIuS " KB\n", |
| 357 lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB, | 354 lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB, |
| 358 lo_space_->CommittedMemory() / KB); | 355 lo_space_->CommittedMemory() / KB); |
| 359 PrintIsolate(isolate_, "All spaces, used: %6" V8PRIdPTR | 356 PrintIsolate(isolate_, "All spaces, used: %6" PRIuS |
| 360 " KB" | 357 " KB" |
| 361 ", available: %6" V8PRIdPTR | 358 ", available: %6" PRIuS |
| 362 " KB" | 359 " KB" |
| 363 ", committed: %6zu KB\n", | 360 ", committed: %6" PRIuS "KB\n", |
| 364 this->SizeOfObjects() / KB, this->Available() / KB, | 361 this->SizeOfObjects() / KB, this->Available() / KB, |
| 365 this->CommittedMemory() / KB); | 362 this->CommittedMemory() / KB); |
| 366 PrintIsolate(isolate_, "External memory reported: %6" V8PRIdPTR " KB\n", | 363 PrintIsolate(isolate_, "External memory reported: %6" PRId64 " KB\n", |
| 367 static_cast<intptr_t>(external_memory_ / KB)); | 364 external_memory_ / KB); |
| 368 PrintIsolate(isolate_, "Total time spent in GC : %.1f ms\n", | 365 PrintIsolate(isolate_, "Total time spent in GC : %.1f ms\n", |
| 369 total_gc_time_ms_); | 366 total_gc_time_ms_); |
| 370 } | 367 } |
| 371 | 368 |
| 372 // TODO(1238405): Combine the infrastructure for --heap-stats and | 369 // TODO(1238405): Combine the infrastructure for --heap-stats and |
| 373 // --log-gc to avoid the complicated preprocessor and flag testing. | 370 // --log-gc to avoid the complicated preprocessor and flag testing. |
| 374 void Heap::ReportStatisticsAfterGC() { | 371 void Heap::ReportStatisticsAfterGC() { |
| 375 // Similar to the before GC, we use some complicated logic to ensure that | 372 // Similar to the before GC, we use some complicated logic to ensure that |
| 376 // NewSpace statistics are logged exactly once when --log-gc is turned on. | 373 // NewSpace statistics are logged exactly once when --log-gc is turned on. |
| 377 #if defined(DEBUG) | 374 #if defined(DEBUG) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 if (new_space_->IsAtMaximumCapacity()) { | 432 if (new_space_->IsAtMaximumCapacity()) { |
| 436 maximum_size_scavenges_++; | 433 maximum_size_scavenges_++; |
| 437 } else { | 434 } else { |
| 438 maximum_size_scavenges_ = 0; | 435 maximum_size_scavenges_ = 0; |
| 439 } | 436 } |
| 440 CheckNewSpaceExpansionCriteria(); | 437 CheckNewSpaceExpansionCriteria(); |
| 441 UpdateNewSpaceAllocationCounter(); | 438 UpdateNewSpaceAllocationCounter(); |
| 442 store_buffer()->MoveAllEntriesToRememberedSet(); | 439 store_buffer()->MoveAllEntriesToRememberedSet(); |
| 443 } | 440 } |
| 444 | 441 |
| 445 | 442 size_t Heap::SizeOfObjects() { |
| 446 intptr_t Heap::SizeOfObjects() { | 443 size_t total = 0; |
| 447 intptr_t total = 0; | |
| 448 AllSpaces spaces(this); | 444 AllSpaces spaces(this); |
| 449 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { | 445 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
| 450 total += space->SizeOfObjects(); | 446 total += space->SizeOfObjects(); |
| 451 } | 447 } |
| 452 return total; | 448 return total; |
| 453 } | 449 } |
| 454 | 450 |
| 455 | 451 |
| 456 const char* Heap::GetSpaceName(int idx) { | 452 const char* Heap::GetSpaceName(int idx) { |
| 457 switch (idx) { | 453 switch (idx) { |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 if (FLAG_trace_incremental_marking) { | 966 if (FLAG_trace_incremental_marking) { |
| 971 isolate()->PrintWithTimestamp( | 967 isolate()->PrintWithTimestamp( |
| 972 "[IncrementalMarking] Delaying MarkSweep.\n"); | 968 "[IncrementalMarking] Delaying MarkSweep.\n"); |
| 973 } | 969 } |
| 974 collector = YoungGenerationCollector(); | 970 collector = YoungGenerationCollector(); |
| 975 collector_reason = "incremental marking delaying mark-sweep"; | 971 collector_reason = "incremental marking delaying mark-sweep"; |
| 976 } | 972 } |
| 977 } | 973 } |
| 978 | 974 |
| 979 bool next_gc_likely_to_collect_more = false; | 975 bool next_gc_likely_to_collect_more = false; |
| 980 intptr_t committed_memory_before = 0; | 976 size_t committed_memory_before = 0; |
| 981 | 977 |
| 982 if (collector == MARK_COMPACTOR) { | 978 if (collector == MARK_COMPACTOR) { |
| 983 committed_memory_before = CommittedOldGenerationMemory(); | 979 committed_memory_before = CommittedOldGenerationMemory(); |
| 984 } | 980 } |
| 985 | 981 |
| 986 { | 982 { |
| 987 tracer()->Start(collector, gc_reason, collector_reason); | 983 tracer()->Start(collector, gc_reason, collector_reason); |
| 988 DCHECK(AllowHeapAllocation::IsAllowed()); | 984 DCHECK(AllowHeapAllocation::IsAllowed()); |
| 989 DisallowHeapAllocation no_allocation_during_gc; | 985 DisallowHeapAllocation no_allocation_during_gc; |
| 990 GarbageCollectionPrologue(); | 986 GarbageCollectionPrologue(); |
| 991 | 987 |
| 992 { | 988 { |
| 993 HistogramTimer* gc_type_timer = GCTypeTimer(collector); | 989 HistogramTimer* gc_type_timer = GCTypeTimer(collector); |
| 994 HistogramTimerScope histogram_timer_scope(gc_type_timer); | 990 HistogramTimerScope histogram_timer_scope(gc_type_timer); |
| 995 TRACE_EVENT0("v8", gc_type_timer->name()); | 991 TRACE_EVENT0("v8", gc_type_timer->name()); |
| 996 | 992 |
| 997 next_gc_likely_to_collect_more = | 993 next_gc_likely_to_collect_more = |
| 998 PerformGarbageCollection(collector, gc_callback_flags); | 994 PerformGarbageCollection(collector, gc_callback_flags); |
| 999 } | 995 } |
| 1000 | 996 |
| 1001 GarbageCollectionEpilogue(); | 997 GarbageCollectionEpilogue(); |
| 1002 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { | 998 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { |
| 1003 isolate()->CheckDetachedContextsAfterGC(); | 999 isolate()->CheckDetachedContextsAfterGC(); |
| 1004 } | 1000 } |
| 1005 | 1001 |
| 1006 if (collector == MARK_COMPACTOR) { | 1002 if (collector == MARK_COMPACTOR) { |
| 1007 intptr_t committed_memory_after = CommittedOldGenerationMemory(); | 1003 size_t committed_memory_after = CommittedOldGenerationMemory(); |
| 1008 intptr_t used_memory_after = PromotedSpaceSizeOfObjects(); | 1004 size_t used_memory_after = PromotedSpaceSizeOfObjects(); |
| 1009 MemoryReducer::Event event; | 1005 MemoryReducer::Event event; |
| 1010 event.type = MemoryReducer::kMarkCompact; | 1006 event.type = MemoryReducer::kMarkCompact; |
| 1011 event.time_ms = MonotonicallyIncreasingTimeInMs(); | 1007 event.time_ms = MonotonicallyIncreasingTimeInMs(); |
| 1012 // Trigger one more GC if | 1008 // Trigger one more GC if |
| 1013 // - this GC decreased committed memory, | 1009 // - this GC decreased committed memory, |
| 1014 // - there is high fragmentation, | 1010 // - there is high fragmentation, |
| 1015 // - there are live detached contexts. | 1011 // - there are live detached contexts. |
| 1016 event.next_gc_likely_to_collect_more = | 1012 event.next_gc_likely_to_collect_more = |
| 1017 (committed_memory_before - committed_memory_after) > MB || | 1013 (committed_memory_before > committed_memory_after + MB) || |
| 1018 HasHighFragmentation(used_memory_after, committed_memory_after) || | 1014 HasHighFragmentation(used_memory_after, committed_memory_after) || |
| 1019 (detached_contexts()->length() > 0); | 1015 (detached_contexts()->length() > 0); |
| 1020 if (deserialization_complete_) { | 1016 if (deserialization_complete_) { |
| 1021 memory_reducer_->NotifyMarkCompact(event); | 1017 memory_reducer_->NotifyMarkCompact(event); |
| 1022 } | 1018 } |
| 1023 memory_pressure_level_.SetValue(MemoryPressureLevel::kNone); | 1019 memory_pressure_level_.SetValue(MemoryPressureLevel::kNone); |
| 1024 } | 1020 } |
| 1025 | 1021 |
| 1026 tracer()->Stop(collector); | 1022 tracer()->Stop(collector); |
| 1027 } | 1023 } |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 gc_post_processing_depth_--; | 1344 gc_post_processing_depth_--; |
| 1349 | 1345 |
| 1350 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1346 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
| 1351 | 1347 |
| 1352 // Update relocatables. | 1348 // Update relocatables. |
| 1353 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1349 Relocatable::PostGarbageCollectionProcessing(isolate_); |
| 1354 | 1350 |
| 1355 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); | 1351 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); |
| 1356 double mutator_speed = | 1352 double mutator_speed = |
| 1357 tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond(); | 1353 tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond(); |
| 1358 intptr_t old_gen_size = PromotedSpaceSizeOfObjects(); | 1354 size_t old_gen_size = PromotedSpaceSizeOfObjects(); |
| 1359 if (collector == MARK_COMPACTOR) { | 1355 if (collector == MARK_COMPACTOR) { |
| 1360 // Register the amount of external allocated memory. | 1356 // Register the amount of external allocated memory. |
| 1361 external_memory_at_last_mark_compact_ = external_memory_; | 1357 external_memory_at_last_mark_compact_ = external_memory_; |
| 1362 external_memory_limit_ = external_memory_ + kExternalAllocationSoftLimit; | 1358 external_memory_limit_ = external_memory_ + kExternalAllocationSoftLimit; |
| 1363 SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); | 1359 SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); |
| 1364 } else if (HasLowYoungGenerationAllocationRate() && | 1360 } else if (HasLowYoungGenerationAllocationRate() && |
| 1365 old_generation_size_configured_) { | 1361 old_generation_size_configured_) { |
| 1366 DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); | 1362 DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); |
| 1367 } | 1363 } |
| 1368 | 1364 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 PauseAllocationObserversScope pause_observers(this); | 1594 PauseAllocationObserversScope pause_observers(this); |
| 1599 | 1595 |
| 1600 mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); | 1596 mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); |
| 1601 | 1597 |
| 1602 gc_state_ = SCAVENGE; | 1598 gc_state_ = SCAVENGE; |
| 1603 | 1599 |
| 1604 // Implements Cheney's copying algorithm | 1600 // Implements Cheney's copying algorithm |
| 1605 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1601 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
| 1606 | 1602 |
| 1607 // Used for updating survived_since_last_expansion_ at function end. | 1603 // Used for updating survived_since_last_expansion_ at function end. |
| 1608 intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); | 1604 size_t survived_watermark = PromotedSpaceSizeOfObjects(); |
| 1609 | 1605 |
| 1610 scavenge_collector_->SelectScavengingVisitorsTable(); | 1606 scavenge_collector_->SelectScavengingVisitorsTable(); |
| 1611 | 1607 |
| 1612 if (UsingEmbedderHeapTracer()) { | 1608 if (UsingEmbedderHeapTracer()) { |
| 1613 // Register found wrappers with embedder so it can add them to its marking | 1609 // Register found wrappers with embedder so it can add them to its marking |
| 1614 // deque and correctly manage the case when v8 scavenger collects the | 1610 // deque and correctly manage the case when v8 scavenger collects the |
| 1615 // wrappers by either keeping wrappables alive, or cleaning marking deque. | 1611 // wrappers by either keeping wrappables alive, or cleaning marking deque. |
| 1616 RegisterWrappersWithEmbedderHeapTracer(); | 1612 RegisterWrappersWithEmbedderHeapTracer(); |
| 1617 } | 1613 } |
| 1618 | 1614 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 ProcessYoungWeakReferences(&weak_object_retainer); | 1706 ProcessYoungWeakReferences(&weak_object_retainer); |
| 1711 | 1707 |
| 1712 DCHECK(new_space_front == new_space_->top()); | 1708 DCHECK(new_space_front == new_space_->top()); |
| 1713 | 1709 |
| 1714 // Set age mark. | 1710 // Set age mark. |
| 1715 new_space_->set_age_mark(new_space_->top()); | 1711 new_space_->set_age_mark(new_space_->top()); |
| 1716 | 1712 |
| 1717 ArrayBufferTracker::FreeDeadInNewSpace(this); | 1713 ArrayBufferTracker::FreeDeadInNewSpace(this); |
| 1718 | 1714 |
| 1719 // Update how much has survived scavenge. | 1715 // Update how much has survived scavenge. |
| 1720 IncrementYoungSurvivorsCounter( | 1716 DCHECK_GE(PromotedSpaceSizeOfObjects(), survived_watermark); |
| 1721 static_cast<int>((PromotedSpaceSizeOfObjects() - survived_watermark) + | 1717 IncrementYoungSurvivorsCounter(PromotedSpaceSizeOfObjects() + |
| 1722 new_space_->Size())); | 1718 new_space_->Size() - survived_watermark); |
| 1723 | 1719 |
| 1724 LOG(isolate_, ResourceEvent("scavenge", "end")); | 1720 LOG(isolate_, ResourceEvent("scavenge", "end")); |
| 1725 | 1721 |
| 1726 gc_state_ = NOT_IN_GC; | 1722 gc_state_ = NOT_IN_GC; |
| 1727 } | 1723 } |
| 1728 | 1724 |
| 1729 | 1725 |
| 1730 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, | 1726 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1731 Object** p) { | 1727 Object** p) { |
| 1732 MapWord first_word = HeapObject::cast(*p)->map_word(); | 1728 MapWord first_word = HeapObject::cast(*p)->map_word(); |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2000 | 1996 |
| 2001 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) { | 1997 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) { |
| 2002 ArrayBufferTracker::Unregister(this, buffer); | 1998 ArrayBufferTracker::Unregister(this, buffer); |
| 2003 } | 1999 } |
| 2004 | 2000 |
| 2005 | 2001 |
| 2006 void Heap::ConfigureInitialOldGenerationSize() { | 2002 void Heap::ConfigureInitialOldGenerationSize() { |
| 2007 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { | 2003 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { |
| 2008 old_generation_allocation_limit_ = | 2004 old_generation_allocation_limit_ = |
| 2009 Max(MinimumAllocationLimitGrowingStep(), | 2005 Max(MinimumAllocationLimitGrowingStep(), |
| 2010 static_cast<intptr_t>( | 2006 static_cast<size_t>( |
| 2011 static_cast<double>(old_generation_allocation_limit_) * | 2007 static_cast<double>(old_generation_allocation_limit_) * |
| 2012 (tracer()->AverageSurvivalRatio() / 100))); | 2008 (tracer()->AverageSurvivalRatio() / 100))); |
| 2013 } | 2009 } |
| 2014 } | 2010 } |
| 2015 | 2011 |
| 2016 | 2012 |
| 2017 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, | 2013 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, |
| 2018 int instance_size) { | 2014 int instance_size) { |
| 2019 Object* result = nullptr; | 2015 Object* result = nullptr; |
| 2020 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE); | 2016 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE); |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) { | 2898 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) { |
| 2903 return !RootCanBeWrittenAfterInitialization(root_index) && | 2899 return !RootCanBeWrittenAfterInitialization(root_index) && |
| 2904 !InNewSpace(root(root_index)); | 2900 !InNewSpace(root(root_index)); |
| 2905 } | 2901 } |
| 2906 | 2902 |
| 2907 | 2903 |
| 2908 int Heap::FullSizeNumberStringCacheLength() { | 2904 int Heap::FullSizeNumberStringCacheLength() { |
| 2909 // Compute the size of the number string cache based on the max newspace size. | 2905 // Compute the size of the number string cache based on the max newspace size. |
| 2910 // The number string cache has a minimum size based on twice the initial cache | 2906 // The number string cache has a minimum size based on twice the initial cache |
| 2911 // size to ensure that it is bigger after being made 'full size'. | 2907 // size to ensure that it is bigger after being made 'full size'. |
| 2912 int number_string_cache_size = max_semi_space_size_ / 512; | 2908 size_t number_string_cache_size = max_semi_space_size_ / 512; |
| 2913 number_string_cache_size = Max(kInitialNumberStringCacheSize * 2, | 2909 number_string_cache_size = |
| 2914 Min(0x4000, number_string_cache_size)); | 2910 Max(static_cast<size_t>(kInitialNumberStringCacheSize * 2), |
| 2911 Min<size_t>(0x4000u, number_string_cache_size)); |
| 2915 // There is a string and a number per entry so the length is twice the number | 2912 // There is a string and a number per entry so the length is twice the number |
| 2916 // of entries. | 2913 // of entries. |
| 2917 return number_string_cache_size * 2; | 2914 return static_cast<int>(number_string_cache_size * 2); |
| 2918 } | 2915 } |
| 2919 | 2916 |
| 2920 | 2917 |
| 2921 void Heap::FlushNumberStringCache() { | 2918 void Heap::FlushNumberStringCache() { |
| 2922 // Flush the number to string cache. | 2919 // Flush the number to string cache. |
| 2923 int len = number_string_cache()->length(); | 2920 int len = number_string_cache()->length(); |
| 2924 for (int i = 0; i < len; i++) { | 2921 for (int i = 0; i < len; i++) { |
| 2925 number_string_cache()->set_undefined(i); | 2922 number_string_cache()->set_undefined(i); |
| 2926 } | 2923 } |
| 2927 } | 2924 } |
| (...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4097 } | 4094 } |
| 4098 | 4095 |
| 4099 | 4096 |
| 4100 bool Heap::HasLowAllocationRate() { | 4097 bool Heap::HasLowAllocationRate() { |
| 4101 return HasLowYoungGenerationAllocationRate() && | 4098 return HasLowYoungGenerationAllocationRate() && |
| 4102 HasLowOldGenerationAllocationRate(); | 4099 HasLowOldGenerationAllocationRate(); |
| 4103 } | 4100 } |
| 4104 | 4101 |
| 4105 | 4102 |
| 4106 bool Heap::HasHighFragmentation() { | 4103 bool Heap::HasHighFragmentation() { |
| 4107 intptr_t used = PromotedSpaceSizeOfObjects(); | 4104 size_t used = PromotedSpaceSizeOfObjects(); |
| 4108 intptr_t committed = CommittedOldGenerationMemory(); | 4105 size_t committed = CommittedOldGenerationMemory(); |
| 4109 return HasHighFragmentation(used, committed); | 4106 return HasHighFragmentation(used, committed); |
| 4110 } | 4107 } |
| 4111 | 4108 |
| 4112 | 4109 bool Heap::HasHighFragmentation(size_t used, size_t committed) { |
| 4113 bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) { | 4110 const size_t kSlack = 16 * MB; |
| 4114 const intptr_t kSlack = 16 * MB; | |
| 4115 // Fragmentation is high if committed > 2 * used + kSlack. | 4111 // Fragmentation is high if committed > 2 * used + kSlack. |
| 4116 // Rewrite the exression to avoid overflow. | 4112 // Rewrite the exression to avoid overflow. |
| 4113 DCHECK_GE(committed, used); |
| 4117 return committed - used > used + kSlack; | 4114 return committed - used > used + kSlack; |
| 4118 } | 4115 } |
| 4119 | 4116 |
| 4120 bool Heap::ShouldOptimizeForMemoryUsage() { | 4117 bool Heap::ShouldOptimizeForMemoryUsage() { |
| 4121 return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() || | 4118 return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() || |
| 4122 HighMemoryPressure() || IsLowMemoryDevice(); | 4119 HighMemoryPressure() || IsLowMemoryDevice(); |
| 4123 } | 4120 } |
| 4124 | 4121 |
| 4125 void Heap::ActivateMemoryReducerIfNeeded() { | 4122 void Heap::ActivateMemoryReducerIfNeeded() { |
| 4126 // Activate memory reducer when switching to background if | 4123 // Activate memory reducer when switching to background if |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4963 // We don't do a v->Synchronize call here, because in debug mode that will | 4960 // We don't do a v->Synchronize call here, because in debug mode that will |
| 4964 // output a flag to the snapshot. However at this point the serializer and | 4961 // output a flag to the snapshot. However at this point the serializer and |
| 4965 // deserializer are deliberately a little unsynchronized (see above) so the | 4962 // deserializer are deliberately a little unsynchronized (see above) so the |
| 4966 // checking of the sync flag in the snapshot would fail. | 4963 // checking of the sync flag in the snapshot would fail. |
| 4967 } | 4964 } |
| 4968 | 4965 |
| 4969 | 4966 |
| 4970 // TODO(1236194): Since the heap size is configurable on the command line | 4967 // TODO(1236194): Since the heap size is configurable on the command line |
| 4971 // and through the API, we should gracefully handle the case that the heap | 4968 // and through the API, we should gracefully handle the case that the heap |
| 4972 // size is not big enough to fit all the initial objects. | 4969 // size is not big enough to fit all the initial objects. |
| 4973 bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size, | 4970 bool Heap::ConfigureHeap(size_t max_semi_space_size, size_t max_old_space_size, |
| 4974 int max_executable_size, size_t code_range_size) { | 4971 size_t max_executable_size, size_t code_range_size) { |
| 4975 if (HasBeenSetUp()) return false; | 4972 if (HasBeenSetUp()) return false; |
| 4976 | 4973 |
| 4977 // Overwrite default configuration. | 4974 // Overwrite default configuration. |
| 4978 if (max_semi_space_size > 0) { | 4975 if (max_semi_space_size != 0) { |
| 4979 max_semi_space_size_ = max_semi_space_size * MB; | 4976 max_semi_space_size_ = max_semi_space_size * MB; |
| 4980 } | 4977 } |
| 4981 if (max_old_space_size > 0) { | 4978 if (max_old_space_size != 0) { |
| 4982 max_old_generation_size_ = static_cast<intptr_t>(max_old_space_size) * MB; | 4979 max_old_generation_size_ = max_old_space_size * MB; |
| 4983 } | 4980 } |
| 4984 if (max_executable_size > 0) { | 4981 if (max_executable_size != 0) { |
| 4985 max_executable_size_ = static_cast<intptr_t>(max_executable_size) * MB; | 4982 max_executable_size_ = max_executable_size * MB; |
| 4986 } | 4983 } |
| 4987 | 4984 |
| 4988 // If max space size flags are specified overwrite the configuration. | 4985 // If max space size flags are specified overwrite the configuration. |
| 4989 if (FLAG_max_semi_space_size > 0) { | 4986 if (FLAG_max_semi_space_size > 0) { |
| 4990 max_semi_space_size_ = FLAG_max_semi_space_size * MB; | 4987 max_semi_space_size_ = static_cast<size_t>(FLAG_max_semi_space_size) * MB; |
| 4991 } | 4988 } |
| 4992 if (FLAG_max_old_space_size > 0) { | 4989 if (FLAG_max_old_space_size > 0) { |
| 4993 max_old_generation_size_ = | 4990 max_old_generation_size_ = |
| 4994 static_cast<intptr_t>(FLAG_max_old_space_size) * MB; | 4991 static_cast<size_t>(FLAG_max_old_space_size) * MB; |
| 4995 } | 4992 } |
| 4996 if (FLAG_max_executable_size > 0) { | 4993 if (FLAG_max_executable_size > 0) { |
| 4997 max_executable_size_ = static_cast<intptr_t>(FLAG_max_executable_size) * MB; | 4994 max_executable_size_ = static_cast<size_t>(FLAG_max_executable_size) * MB; |
| 4998 } | 4995 } |
| 4999 | 4996 |
| 5000 if (Page::kPageSize > MB) { | 4997 if (Page::kPageSize > MB) { |
| 5001 max_semi_space_size_ = ROUND_UP(max_semi_space_size_, Page::kPageSize); | 4998 max_semi_space_size_ = ROUND_UP(max_semi_space_size_, Page::kPageSize); |
| 5002 max_old_generation_size_ = | 4999 max_old_generation_size_ = |
| 5003 ROUND_UP(max_old_generation_size_, Page::kPageSize); | 5000 ROUND_UP(max_old_generation_size_, Page::kPageSize); |
| 5004 max_executable_size_ = ROUND_UP(max_executable_size_, Page::kPageSize); | 5001 max_executable_size_ = ROUND_UP(max_executable_size_, Page::kPageSize); |
| 5005 } | 5002 } |
| 5006 | 5003 |
| 5007 if (FLAG_stress_compaction) { | 5004 if (FLAG_stress_compaction) { |
| 5008 // This will cause more frequent GCs when stressing. | 5005 // This will cause more frequent GCs when stressing. |
| 5009 max_semi_space_size_ = MB; | 5006 max_semi_space_size_ = MB; |
| 5010 } | 5007 } |
| 5011 | 5008 |
| 5012 // The new space size must be a power of two to support single-bit testing | 5009 // The new space size must be a power of two to support single-bit testing |
| 5013 // for containment. | 5010 // for containment. |
| 5014 max_semi_space_size_ = | 5011 max_semi_space_size_ = base::bits::RoundUpToPowerOfTwo32( |
| 5015 base::bits::RoundUpToPowerOfTwo32(max_semi_space_size_); | 5012 static_cast<uint32_t>(max_semi_space_size_)); |
| 5016 | 5013 |
| 5017 if (FLAG_min_semi_space_size > 0) { | 5014 if (FLAG_min_semi_space_size > 0) { |
| 5018 int initial_semispace_size = FLAG_min_semi_space_size * MB; | 5015 size_t initial_semispace_size = |
| 5016 static_cast<size_t>(FLAG_min_semi_space_size) * MB; |
| 5019 if (initial_semispace_size > max_semi_space_size_) { | 5017 if (initial_semispace_size > max_semi_space_size_) { |
| 5020 initial_semispace_size_ = max_semi_space_size_; | 5018 initial_semispace_size_ = max_semi_space_size_; |
| 5021 if (FLAG_trace_gc) { | 5019 if (FLAG_trace_gc) { |
| 5022 PrintIsolate(isolate_, | 5020 PrintIsolate(isolate_, |
| 5023 "Min semi-space size cannot be more than the maximum " | 5021 "Min semi-space size cannot be more than the maximum " |
| 5024 "semi-space size of %d MB\n", | 5022 "semi-space size of %" PRIuS " MB\n", |
| 5025 max_semi_space_size_ / MB); | 5023 max_semi_space_size_ / MB); |
| 5026 } | 5024 } |
| 5027 } else { | 5025 } else { |
| 5028 initial_semispace_size_ = | 5026 initial_semispace_size_ = |
| 5029 ROUND_UP(initial_semispace_size, Page::kPageSize); | 5027 ROUND_UP(initial_semispace_size, Page::kPageSize); |
| 5030 } | 5028 } |
| 5031 } | 5029 } |
| 5032 | 5030 |
| 5033 initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_); | 5031 initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_); |
| 5034 | 5032 |
| 5035 if (FLAG_semi_space_growth_factor < 2) { | 5033 if (FLAG_semi_space_growth_factor < 2) { |
| 5036 FLAG_semi_space_growth_factor = 2; | 5034 FLAG_semi_space_growth_factor = 2; |
| 5037 } | 5035 } |
| 5038 | 5036 |
| 5039 // The old generation is paged and needs at least one page for each space. | 5037 // The old generation is paged and needs at least one page for each space. |
| 5040 int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; | 5038 int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; |
| 5041 max_old_generation_size_ = | 5039 max_old_generation_size_ = |
| 5042 Max(static_cast<intptr_t>(paged_space_count * Page::kPageSize), | 5040 Max(static_cast<size_t>(paged_space_count * Page::kPageSize), |
| 5043 max_old_generation_size_); | 5041 max_old_generation_size_); |
| 5044 | 5042 |
| 5045 // The max executable size must be less than or equal to the max old | 5043 // The max executable size must be less than or equal to the max old |
| 5046 // generation size. | 5044 // generation size. |
| 5047 if (max_executable_size_ > max_old_generation_size_) { | 5045 if (max_executable_size_ > max_old_generation_size_) { |
| 5048 max_executable_size_ = max_old_generation_size_; | 5046 max_executable_size_ = max_old_generation_size_; |
| 5049 } | 5047 } |
| 5050 | 5048 |
| 5051 if (FLAG_initial_old_space_size > 0) { | 5049 if (FLAG_initial_old_space_size > 0) { |
| 5052 initial_old_generation_size_ = FLAG_initial_old_space_size * MB; | 5050 initial_old_generation_size_ = FLAG_initial_old_space_size * MB; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5131 FixedStringAllocator fixed(stats->js_stacktrace, kStacktraceBufferSize - 1); | 5129 FixedStringAllocator fixed(stats->js_stacktrace, kStacktraceBufferSize - 1); |
| 5132 StringStream accumulator(&fixed, StringStream::kPrintObjectConcise); | 5130 StringStream accumulator(&fixed, StringStream::kPrintObjectConcise); |
| 5133 if (gc_state() == Heap::NOT_IN_GC) { | 5131 if (gc_state() == Heap::NOT_IN_GC) { |
| 5134 isolate()->PrintStack(&accumulator, Isolate::kPrintStackVerbose); | 5132 isolate()->PrintStack(&accumulator, Isolate::kPrintStackVerbose); |
| 5135 } else { | 5133 } else { |
| 5136 accumulator.Add("Cannot get stack trace in GC."); | 5134 accumulator.Add("Cannot get stack trace in GC."); |
| 5137 } | 5135 } |
| 5138 } | 5136 } |
| 5139 } | 5137 } |
| 5140 | 5138 |
| 5141 | 5139 size_t Heap::PromotedSpaceSizeOfObjects() { |
| 5142 intptr_t Heap::PromotedSpaceSizeOfObjects() { | |
| 5143 return old_space_->SizeOfObjects() + code_space_->SizeOfObjects() + | 5140 return old_space_->SizeOfObjects() + code_space_->SizeOfObjects() + |
| 5144 map_space_->SizeOfObjects() + lo_space_->SizeOfObjects(); | 5141 map_space_->SizeOfObjects() + lo_space_->SizeOfObjects(); |
| 5145 } | 5142 } |
| 5146 | 5143 |
| 5147 | 5144 uint64_t Heap::PromotedExternalMemorySize() { |
| 5148 int64_t Heap::PromotedExternalMemorySize() { | |
| 5149 if (external_memory_ <= external_memory_at_last_mark_compact_) return 0; | 5145 if (external_memory_ <= external_memory_at_last_mark_compact_) return 0; |
| 5150 return external_memory_ - external_memory_at_last_mark_compact_; | 5146 return static_cast<uint64_t>(external_memory_ - |
| 5147 external_memory_at_last_mark_compact_); |
| 5151 } | 5148 } |
| 5152 | 5149 |
| 5153 | 5150 |
| 5154 const double Heap::kMinHeapGrowingFactor = 1.1; | 5151 const double Heap::kMinHeapGrowingFactor = 1.1; |
| 5155 const double Heap::kMaxHeapGrowingFactor = 4.0; | 5152 const double Heap::kMaxHeapGrowingFactor = 4.0; |
| 5156 const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0; | 5153 const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0; |
| 5157 const double Heap::kMaxHeapGrowingFactorIdle = 1.5; | 5154 const double Heap::kMaxHeapGrowingFactorIdle = 1.5; |
| 5158 const double Heap::kConservativeHeapGrowingFactor = 1.3; | 5155 const double Heap::kConservativeHeapGrowingFactor = 1.3; |
| 5159 const double Heap::kTargetMutatorUtilization = 0.97; | 5156 const double Heap::kTargetMutatorUtilization = 0.97; |
| 5160 | 5157 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5208 const double b = speed_ratio * (1 - mu) - mu; | 5205 const double b = speed_ratio * (1 - mu) - mu; |
| 5209 | 5206 |
| 5210 // The factor is a / b, but we need to check for small b first. | 5207 // The factor is a / b, but we need to check for small b first. |
| 5211 double factor = | 5208 double factor = |
| 5212 (a < b * kMaxHeapGrowingFactor) ? a / b : kMaxHeapGrowingFactor; | 5209 (a < b * kMaxHeapGrowingFactor) ? a / b : kMaxHeapGrowingFactor; |
| 5213 factor = Min(factor, kMaxHeapGrowingFactor); | 5210 factor = Min(factor, kMaxHeapGrowingFactor); |
| 5214 factor = Max(factor, kMinHeapGrowingFactor); | 5211 factor = Max(factor, kMinHeapGrowingFactor); |
| 5215 return factor; | 5212 return factor; |
| 5216 } | 5213 } |
| 5217 | 5214 |
| 5218 | 5215 size_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
| 5219 intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, | 5216 size_t old_gen_size) { |
| 5220 intptr_t old_gen_size) { | |
| 5221 CHECK(factor > 1.0); | 5217 CHECK(factor > 1.0); |
| 5222 CHECK(old_gen_size > 0); | 5218 CHECK(old_gen_size > 0); |
| 5223 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | 5219 uint64_t limit = static_cast<uint64_t>(old_gen_size * factor); |
| 5224 limit = Max(limit, old_gen_size + MinimumAllocationLimitGrowingStep()); | 5220 limit = Max(limit, static_cast<uint64_t>(old_gen_size) + |
| 5221 MinimumAllocationLimitGrowingStep()); |
| 5225 limit += new_space_->Capacity(); | 5222 limit += new_space_->Capacity(); |
| 5226 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | 5223 uint64_t halfway_to_the_max = |
| 5227 return Min(limit, halfway_to_the_max); | 5224 (static_cast<uint64_t>(old_gen_size) + max_old_generation_size_) / 2; |
| 5225 return static_cast<size_t>(Min(limit, halfway_to_the_max)); |
| 5228 } | 5226 } |
| 5229 | 5227 |
| 5230 intptr_t Heap::MinimumAllocationLimitGrowingStep() { | 5228 size_t Heap::MinimumAllocationLimitGrowingStep() { |
| 5231 const double kRegularAllocationLimitGrowingStep = 8; | 5229 const size_t kRegularAllocationLimitGrowingStep = 8; |
| 5232 const double kLowMemoryAllocationLimitGrowingStep = 2; | 5230 const size_t kLowMemoryAllocationLimitGrowingStep = 2; |
| 5233 intptr_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB); | 5231 size_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB); |
| 5234 return limit * (ShouldOptimizeForMemoryUsage() | 5232 return limit * (ShouldOptimizeForMemoryUsage() |
| 5235 ? kLowMemoryAllocationLimitGrowingStep | 5233 ? kLowMemoryAllocationLimitGrowingStep |
| 5236 : kRegularAllocationLimitGrowingStep); | 5234 : kRegularAllocationLimitGrowingStep); |
| 5237 } | 5235 } |
| 5238 | 5236 |
| 5239 void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, | 5237 void Heap::SetOldGenerationAllocationLimit(size_t old_gen_size, double gc_speed, |
| 5240 double gc_speed, | |
| 5241 double mutator_speed) { | 5238 double mutator_speed) { |
| 5242 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5239 double factor = HeapGrowingFactor(gc_speed, mutator_speed); |
| 5243 | 5240 |
| 5244 if (FLAG_trace_gc_verbose) { | 5241 if (FLAG_trace_gc_verbose) { |
| 5245 isolate_->PrintWithTimestamp( | 5242 isolate_->PrintWithTimestamp( |
| 5246 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " | 5243 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " |
| 5247 "(gc=%.f, mutator=%.f)\n", | 5244 "(gc=%.f, mutator=%.f)\n", |
| 5248 factor, kTargetMutatorUtilization, gc_speed / mutator_speed, gc_speed, | 5245 factor, kTargetMutatorUtilization, gc_speed / mutator_speed, gc_speed, |
| 5249 mutator_speed); | 5246 mutator_speed); |
| 5250 } | 5247 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5263 } | 5260 } |
| 5264 | 5261 |
| 5265 if (FLAG_heap_growing_percent > 0) { | 5262 if (FLAG_heap_growing_percent > 0) { |
| 5266 factor = 1.0 + FLAG_heap_growing_percent / 100.0; | 5263 factor = 1.0 + FLAG_heap_growing_percent / 100.0; |
| 5267 } | 5264 } |
| 5268 | 5265 |
| 5269 old_generation_allocation_limit_ = | 5266 old_generation_allocation_limit_ = |
| 5270 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5267 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
| 5271 | 5268 |
| 5272 if (FLAG_trace_gc_verbose) { | 5269 if (FLAG_trace_gc_verbose) { |
| 5273 isolate_->PrintWithTimestamp("Grow: old size: %" V8PRIdPTR | 5270 isolate_->PrintWithTimestamp( |
| 5274 " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5271 "Grow: old size: %" PRIuS " KB, new limit: %" PRIuS " KB (%.1f)\n", |
| 5275 old_gen_size / KB, | 5272 old_gen_size / KB, old_generation_allocation_limit_ / KB, factor); |
| 5276 old_generation_allocation_limit_ / KB, factor); | |
| 5277 } | 5273 } |
| 5278 } | 5274 } |
| 5279 | 5275 |
| 5280 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, | 5276 void Heap::DampenOldGenerationAllocationLimit(size_t old_gen_size, |
| 5281 double gc_speed, | 5277 double gc_speed, |
| 5282 double mutator_speed) { | 5278 double mutator_speed) { |
| 5283 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5279 double factor = HeapGrowingFactor(gc_speed, mutator_speed); |
| 5284 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5280 size_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
| 5285 if (limit < old_generation_allocation_limit_) { | 5281 if (limit < old_generation_allocation_limit_) { |
| 5286 if (FLAG_trace_gc_verbose) { | 5282 if (FLAG_trace_gc_verbose) { |
| 5287 isolate_->PrintWithTimestamp( | 5283 isolate_->PrintWithTimestamp( |
| 5288 "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR | 5284 "Dampen: old size: %" PRIuS " KB, old limit: %" PRIuS |
| 5289 " KB, " | 5285 " KB, " |
| 5290 "new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5286 "new limit: %" PRIuS " KB (%.1f)\n", |
| 5291 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, | 5287 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, |
| 5292 factor); | 5288 factor); |
| 5293 } | 5289 } |
| 5294 old_generation_allocation_limit_ = limit; | 5290 old_generation_allocation_limit_ = limit; |
| 5295 } | 5291 } |
| 5296 } | 5292 } |
| 5297 | 5293 |
| 5298 // This predicate is called when an old generation space cannot allocated from | 5294 // This predicate is called when an old generation space cannot allocated from |
| 5299 // the free list and is about to add a new page. Returning false will cause a | 5295 // the free list and is about to add a new page. Returning false will cause a |
| 5300 // major GC. It happens when the old generation allocation limit is reached and | 5296 // major GC. It happens when the old generation allocation limit is reached and |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5314 return true; | 5310 return true; |
| 5315 } | 5311 } |
| 5316 | 5312 |
| 5317 // This function returns either kNoLimit, kSoftLimit, or kHardLimit. | 5313 // This function returns either kNoLimit, kSoftLimit, or kHardLimit. |
| 5318 // The kNoLimit means that either incremental marking is disabled or it is too | 5314 // The kNoLimit means that either incremental marking is disabled or it is too |
| 5319 // early to start incremental marking. | 5315 // early to start incremental marking. |
| 5320 // The kSoftLimit means that incremental marking should be started soon. | 5316 // The kSoftLimit means that incremental marking should be started soon. |
| 5321 // The kHardLimit means that incremental marking should be started immediately. | 5317 // The kHardLimit means that incremental marking should be started immediately. |
| 5322 Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() { | 5318 Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() { |
| 5323 if (!incremental_marking()->CanBeActivated() || | 5319 if (!incremental_marking()->CanBeActivated() || |
| 5324 PromotedSpaceSizeOfObjects() < IncrementalMarking::kActivationThreshold) { | 5320 PromotedSpaceSizeOfObjects() <= |
| 5321 IncrementalMarking::kActivationThreshold) { |
| 5325 // Incremental marking is disabled or it is too early to start. | 5322 // Incremental marking is disabled or it is too early to start. |
| 5326 return IncrementalMarkingLimit::kNoLimit; | 5323 return IncrementalMarkingLimit::kNoLimit; |
| 5327 } | 5324 } |
| 5328 if ((FLAG_stress_compaction && (gc_count_ & 1) != 0) || | 5325 if ((FLAG_stress_compaction && (gc_count_ & 1) != 0) || |
| 5329 HighMemoryPressure()) { | 5326 HighMemoryPressure()) { |
| 5330 // If there is high memory pressure or stress testing is enabled, then | 5327 // If there is high memory pressure or stress testing is enabled, then |
| 5331 // start marking immediately. | 5328 // start marking immediately. |
| 5332 return IncrementalMarkingLimit::kHardLimit; | 5329 return IncrementalMarkingLimit::kHardLimit; |
| 5333 } | 5330 } |
| 5334 intptr_t old_generation_space_available = OldGenerationSpaceAvailable(); | 5331 size_t old_generation_space_available = OldGenerationSpaceAvailable(); |
| 5335 if (old_generation_space_available > new_space_->Capacity()) { | 5332 if (old_generation_space_available > new_space_->Capacity()) { |
| 5336 return IncrementalMarkingLimit::kNoLimit; | 5333 return IncrementalMarkingLimit::kNoLimit; |
| 5337 } | 5334 } |
| 5338 // We are close to the allocation limit. | 5335 // We are close to the allocation limit. |
| 5339 // Choose between the hard and the soft limits. | 5336 // Choose between the hard and the soft limits. |
| 5340 if (old_generation_space_available <= 0 || ShouldOptimizeForMemoryUsage()) { | 5337 if (old_generation_space_available == 0 || ShouldOptimizeForMemoryUsage()) { |
| 5341 return IncrementalMarkingLimit::kHardLimit; | 5338 return IncrementalMarkingLimit::kHardLimit; |
| 5342 } | 5339 } |
| 5343 return IncrementalMarkingLimit::kSoftLimit; | 5340 return IncrementalMarkingLimit::kSoftLimit; |
| 5344 } | 5341 } |
| 5345 | 5342 |
| 5346 void Heap::EnableInlineAllocation() { | 5343 void Heap::EnableInlineAllocation() { |
| 5347 if (!inline_allocation_disabled_) return; | 5344 if (!inline_allocation_disabled_) return; |
| 5348 inline_allocation_disabled_ = false; | 5345 inline_allocation_disabled_ = false; |
| 5349 | 5346 |
| 5350 // Update inline allocation limit for new space. | 5347 // Update inline allocation limit for new space. |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6465 } | 6462 } |
| 6466 | 6463 |
| 6467 | 6464 |
| 6468 // static | 6465 // static |
| 6469 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6466 int Heap::GetStaticVisitorIdForMap(Map* map) { |
| 6470 return StaticVisitorBase::GetVisitorId(map); | 6467 return StaticVisitorBase::GetVisitorId(map); |
| 6471 } | 6468 } |
| 6472 | 6469 |
| 6473 } // namespace internal | 6470 } // namespace internal |
| 6474 } // namespace v8 | 6471 } // namespace v8 |
| OLD | NEW |