mark_sweep.cc revision 5712d5d04640925970db9c98938ffaf806b3962c
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
1669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "mark_sweep.h"
1869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
192b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier#include <functional>
202b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier#include <numeric>
2158551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro#include <climits>
2258551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro#include <vector>
2358551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
2494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier#include "base/bounded_fifo.h"
2507ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
26761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
27693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "base/mutex-inl.h"
28a84395489098e4531619b1cffd1afc282b14510eSameer Abu Asal#include "base/timing_logger.h"
291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h"
301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/heap_bitmap.h"
311d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/space_bitmap-inl.h"
321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
331d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/image_space.h"
341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h"
351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h"
36410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes#include "indirect_reference_table.h"
37410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes#include "intern_table.h"
3881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#include "jni_internal.h"
39c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes#include "monitor.h"
402dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mark_sweep-inl.h"
41ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field.h"
42ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h"
432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
452dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/dex_cache.h"
462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array.h"
482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
491f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
501d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "thread-inl.h"
516f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier#include "thread_list.h"
5208254278f290c2541cecd24ce6b7015427f4eae5Ian Rogers#include "verifier/method_verifier.h"
5369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
54ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromusing ::art::mirror::ArtField;
553e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Class;
563e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Object;
573e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::ObjectArray;
582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
5969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapironamespace art {
601d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace gc {
611d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace collector {
6269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
6302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier// Performance options.
6494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kUseRecursiveMark = false;
6594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kUseMarkStackPrefetch = true;
6694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr size_t kSweepArrayChunkFreeSize = 1024;
6794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
6894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// Parallelism options.
6994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kParallelCardScan = true;
7094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kParallelRecursiveMark = true;
7194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// Don't attempt to parallelize mark stack processing unless the mark stack is at least n
7294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// elements. This is temporary until we reduce the overhead caused by allocating tasks, etc.. Not
7394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// having this can add overhead in ProcessReferences since we may end up doing many calls of
7494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// ProcessMarkStack with very small mark stacks.
7594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr size_t kMinimumParallelMarkStackSize = 128;
7694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kParallelProcessMarkStack = true;
77858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
7802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier// Profiling and information flags.
7994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kCountClassesMarked = false;
8094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kProfileLargeObjects = false;
8194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kMeasureOverhead = false;
8294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kCountTasks = false;
8394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kCountJavaLangRefs = false;
8494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
8594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// Turn off kCheckLocks when profiling the GC since it slows the GC down by up to 40%.
8694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierconstexpr bool kCheckLocks = kDebugLocking;
8702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
881d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::ImmuneSpace(space::ContinuousSpace* space) {
892b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Bind live to mark bitmap if necessary.
902b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (space->GetLiveBitmap() != space->GetMarkBitmap()) {
912b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    BindLiveToMarkBitmap(space);
922b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
932b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
942b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Add the space to the immune region.
952b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (immune_begin_ == NULL) {
962b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    DCHECK(immune_end_ == NULL);
972b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    SetImmuneRange(reinterpret_cast<Object*>(space->Begin()),
982b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier                   reinterpret_cast<Object*>(space->End()));
992b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  } else {
10002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    const space::ContinuousSpace* prev_space = nullptr;
1011d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // Find out if the previous space is immune.
10202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (space::ContinuousSpace* cur_space : GetHeap()->GetContinuousSpaces()) {
10302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      if (cur_space == space) {
1041d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        break;
1052b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      }
10602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      prev_space = cur_space;
1071d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    }
1081d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // If previous space was immune, then extend the immune region. Relies on continuous spaces
1091d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // being sorted by Heap::AddContinuousSpace.
1101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (prev_space != NULL &&
1111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        immune_begin_ <= reinterpret_cast<Object*>(prev_space->Begin()) &&
1121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        immune_end_ >= reinterpret_cast<Object*>(prev_space->End())) {
1132b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      immune_begin_ = std::min(reinterpret_cast<Object*>(space->Begin()), immune_begin_);
1142b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      immune_end_ = std::max(reinterpret_cast<Object*>(space->End()), immune_end_);
1152b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    }
1162b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
1172b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
1182b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1192b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::BindBitmaps() {
1204446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("BindBitmaps");
1212b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
1222b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Mark all of the spaces we never collect as immune.
12394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
1241d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect) {
1252b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      ImmuneSpace(space);
1262b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    }
1272b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
1284446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
1292b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
1302b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1311d54e73444e017d3a65234e0f193846f3e27472bIan RogersMarkSweep::MarkSweep(Heap* heap, bool is_concurrent, const std::string& name_prefix)
1321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    : GarbageCollector(heap,
1331d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       name_prefix + (name_prefix.empty() ? "" : " ") +
1341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                       (is_concurrent ? "concurrent mark sweep": "mark sweep")),
1351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      current_mark_bitmap_(NULL),
1361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      java_lang_Class_(NULL),
1371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      mark_stack_(NULL),
1381d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      immune_begin_(NULL),
1391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      immune_end_(NULL),
1401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      soft_reference_list_(NULL),
1411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      weak_reference_list_(NULL),
1421d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      finalizer_reference_list_(NULL),
1431d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      phantom_reference_list_(NULL),
1441d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      cleared_reference_list_(NULL),
14535883cc623fdf475a4ead1dafcba9e9becc1ed11Mathieu Chartier      gc_barrier_(new Barrier(0)),
14662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      large_object_lock_("mark sweep large object lock", kMarkSweepLargeObjectLock),
147958291c7afe723d846a39539fd00410c102485f3Mathieu Chartier      mark_stack_lock_("mark sweep mark stack lock", kMarkSweepMarkStackLock),
1481bd4b4ca7f4f44c55ded050e5a6be09811e1b283Ian Rogers      is_concurrent_(is_concurrent),
1491d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      clear_soft_references_(false) {
1505301cd241b4d8afbfc1211e107c41f1b15c6bd48Mathieu Chartier}
151b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
1522b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::InitializePhase() {
1531d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  timings_.Reset();
1544654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("InitializePhase", &timings_);
155e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  mark_stack_ = heap_->mark_stack_.get();
156e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  DCHECK(mark_stack_ != nullptr);
157e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  SetImmuneRange(nullptr, nullptr);
158e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  soft_reference_list_ = nullptr;
159e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  weak_reference_list_ = nullptr;
160e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  finalizer_reference_list_ = nullptr;
161e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  phantom_reference_list_ = nullptr;
162e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  cleared_reference_list_ = nullptr;
1632b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  freed_bytes_ = 0;
164e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_object_bytes_ = 0;
1652b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  freed_objects_ = 0;
166e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_objects_ = 0;
1672b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  class_count_ = 0;
1682b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  array_count_ = 0;
1692b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  other_count_ = 0;
1702b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  large_object_test_ = 0;
1712b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  large_object_mark_ = 0;
1722b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  classes_marked_ = 0;
1732b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  overhead_time_ = 0;
1742b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  work_chunks_created_ = 0;
1752b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  work_chunks_deleted_ = 0;
1762b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  reference_count_ = 0;
17702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  java_lang_Class_ = Class::GetJavaLangClass();
178e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  CHECK(java_lang_Class_ != nullptr);
1794446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum
1807469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  FindDefaultMarkBitmap();
1814446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum
18294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Do any pre GC verification.
1834654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("PreGcVerification");
1842b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap_->PreGcVerification(this);
1852b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
1862b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1872b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::ProcessReferences(Thread* self) {
1889e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier  base::TimingLogger::ScopedSplit split("ProcessReferences", &timings_);
1898e56c7e41cb37e2eaf553503968a01ff893b135bMathieu Chartier  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
1902b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  ProcessReferences(&soft_reference_list_, clear_soft_references_, &weak_reference_list_,
1912b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier                    &finalizer_reference_list_, &phantom_reference_list_);
1922b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
1932b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1942b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartierbool MarkSweep::HandleDirtyObjectsPhase() {
1954654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("HandleDirtyObjectsPhase", &timings_);
1962b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  Thread* self = Thread::Current();
1972b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  Locks::mutator_lock_->AssertExclusiveHeld(self);
1982b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1992b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  {
2002b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2012b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2022b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // Re-mark root set.
2032b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    ReMarkRoots();
2042b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2052b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // Scan dirty objects, this is only required if we are not doing concurrent GC.
20694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    RecursiveMarkDirtyObjects(true, accounting::CardTable::kCardDirty);
2072b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
2082b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2092b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  ProcessReferences(self);
2109e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier  {
2119e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2129e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier    SweepSystemWeaks();
2139e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier  }
2142b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2152b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Only need to do this if we have the card mark verification on, and only during concurrent GC.
2162b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (GetHeap()->verify_missing_card_marks_) {
2172b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2182b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // This second sweep makes sure that we don't have any objects in the live stack which point to
2192b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // freed objects. These cause problems since their references may be previously freed objects.
22094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    SweepArray(GetHeap()->allocation_stack_.get(), false);
2212b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
2222b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  return true;
2232b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
2242b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2252b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartierbool MarkSweep::IsConcurrent() const {
2262b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  return is_concurrent_;
2272b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
2282b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2292b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::MarkingPhase() {
2304654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("MarkingPhase", &timings_);
2312b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  Heap* heap = GetHeap();
2322b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  Thread* self = Thread::Current();
2332b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2342b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  BindBitmaps();
2352b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  FindDefaultMarkBitmap();
2364446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum
2372b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Process dirty cards and add dirty cards to mod union tables.
2382b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap->ProcessCards(timings_);
2392b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2402b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Need to do this before the checkpoint since we don't want any threads to add references to
2412b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // the live stack during the recursive mark.
2424654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("SwapStacks");
2432b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap->SwapStacks();
2442b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2452b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2462b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
2472b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // If we exclusively hold the mutator lock, all threads must be suspended.
2482b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    MarkRoots();
2492b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  } else {
25094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    MarkThreadRoots(self);
2512b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    MarkNonThreadRoots();
2522b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
2532b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  MarkConcurrentRoots();
2542b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2552b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap->UpdateAndMarkModUnion(this, timings_, GetGcType());
2562b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  MarkReachableObjects();
2572b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
2582b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
25994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiervoid MarkSweep::MarkThreadRoots(Thread* self) {
26094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  MarkRootsCheckpoint(self);
26194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier}
26294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
2632b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::MarkReachableObjects() {
2642b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Mark everything allocated since the last as GC live so that we can sweep concurrently,
2652b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // knowing that new allocations won't be marked as live.
2664446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("MarkStackAsLive");
2671d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::ObjectStack* live_stack = heap_->GetLiveStack();
2682b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap_->MarkAllocStack(heap_->alloc_space_->GetLiveBitmap(),
26994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                        heap_->large_object_space_->GetLiveObjects(), live_stack);
2702b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  live_stack->Reset();
2714446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
2722b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Recursively mark all the non-image bits set in the mark bitmap.
2732b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  RecursiveMark();
2742b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
2752b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2762b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::ReclaimPhase() {
2774654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("ReclaimPhase", &timings_);
278720ef7680573c1afd12f99f02eee3045daee5168Mathieu Chartier  Thread* self = Thread::Current();
2792b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
2802b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (!IsConcurrent()) {
2812b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    ProcessReferences(self);
2829e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2839e452d1d097bc0f29a24e13ced5477fa3c9463f9Mathieu Chartier    SweepSystemWeaks();
2849642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  } else {
285a9a50926963b5093fb851ed966d201f3e95f72d3Anwar Ghuloum    base::TimingLogger::ScopedSplit split("UnMarkAllocStack", &timings_);
2869642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    accounting::ObjectStack* allocation_stack = GetHeap()->allocation_stack_.get();
2879642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
2889642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // The allocation stack contains things allocated since the start of the GC. These may have been
2899642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // marked during this GC meaning they won't be eligible for reclaiming in the next sticky GC.
2909642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // Remove these objects from the mark bitmaps so that they will be eligible for sticky
2919642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // collection.
2929642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // There is a race here which is safely handled. Another thread such as the hprof could
2939642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // have flushed the alloc stack after we resumed the threads. This is safe however, since
2949642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // reseting the allocation stack zeros it out with madvise. This means that we will either
2959642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // read NULLs or attempt to unmark a newly allocated object which will not be marked in the
2969642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    // first place.
2979642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    mirror::Object** end = allocation_stack->End();
2989642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    for (mirror::Object** it = allocation_stack->Begin(); it != end; ++it) {
29994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      const Object* obj = *it;
3009642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      if (obj != NULL) {
3019642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier        UnMarkObjectNonNull(obj);
3029642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      }
3039642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    }
3042b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
3052b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3062b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Before freeing anything, lets verify the heap.
3072b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (kIsDebugBuild) {
3082b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
3092b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    VerifyImageRoots();
3102b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
3114446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("PreSweepingGcVerification");
3122b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  heap_->PreSweepingGcVerification(this);
3134446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
3142b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3152b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  {
3162b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
3172b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3182b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // Reclaim unmarked objects.
3191d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    Sweep(false);
3202b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3212b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // Swap the live and mark bitmaps for each space which we modified space. This is an
3222b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // optimization that enables us to not clear live bits inside of the sweep. Only swaps unbound
3232b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // bitmaps.
3244446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum    timings_.StartSplit("SwapBitmaps");
3252b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    SwapBitmaps();
3264446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum    timings_.EndSplit();
3272b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3282b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    // Unbind the live and mark bitmaps.
3292b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    UnBindBitmaps();
3302b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
3312b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
3322b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
3332b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::SetImmuneRange(Object* begin, Object* end) {
3342b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  immune_begin_ = begin;
3352b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  immune_end_ = end;
3367469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
33758551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
3387469ebf3888b8037421cb6834f37f946646265ecMathieu Chartiervoid MarkSweep::FindDefaultMarkBitmap() {
3394654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("FindDefaultMarkBitmap", &timings_);
34002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
3411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect) {
34202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      current_mark_bitmap_ = space->GetMarkBitmap();
3437469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      CHECK(current_mark_bitmap_ != NULL);
3447469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      return;
345b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
346b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  }
3477469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  GetHeap()->DumpSpaces();
3487469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  LOG(FATAL) << "Could not find a default mark bitmap";
34958551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro}
35058551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
351ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartiervoid MarkSweep::ExpandMarkStack() {
352ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier  ResizeMarkStack(mark_stack_->Capacity() * 2);
353ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier}
354ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier
355ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartiervoid MarkSweep::ResizeMarkStack(size_t new_size) {
356ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  // Rare case, no need to have Thread::Current be a parameter.
357ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  if (UNLIKELY(mark_stack_->Size() < mark_stack_->Capacity())) {
358ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier    // Someone else acquired the lock and expanded the mark stack before us.
359ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier    return;
360ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  }
36102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  std::vector<Object*> temp(mark_stack_->Begin(), mark_stack_->End());
362ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier  CHECK_LE(mark_stack_->Size(), new_size);
363ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier  mark_stack_->Resize(new_size);
36402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& obj : temp) {
36502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    mark_stack_->PushBack(obj);
366ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  }
367ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier}
368ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier
3699642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartierinline void MarkSweep::MarkObjectNonNullParallel(const Object* obj) {
370ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  DCHECK(obj != NULL);
371ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  if (MarkObjectParallel(obj)) {
372ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    MutexLock mu(Thread::Current(), mark_stack_lock_);
373ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    if (UNLIKELY(mark_stack_->Size() >= mark_stack_->Capacity())) {
374184e322fe8ddd75c844a1eb2eb1ca32bc02f2d45Mathieu Chartier      ExpandMarkStack();
375ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier    }
376ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    // The object must be pushed on to the mark stack.
377ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    mark_stack_->PushBack(const_cast<Object*>(obj));
378ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  }
379ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier}
380ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier
3819642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartierinline void MarkSweep::UnMarkObjectNonNull(const Object* obj) {
3829642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  DCHECK(!IsImmune(obj));
3839642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  // Try to take advantage of locality of references within a space, failing this find the space
3849642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  // the hard way.
3859642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  accounting::SpaceBitmap* object_bitmap = current_mark_bitmap_;
3869642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  if (UNLIKELY(!object_bitmap->HasAddress(obj))) {
3879642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    accounting::SpaceBitmap* new_bitmap = heap_->GetMarkBitmap()->GetContinuousSpaceBitmap(obj);
3889642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    if (LIKELY(new_bitmap != NULL)) {
3899642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      object_bitmap = new_bitmap;
3909642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    } else {
3919642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      MarkLargeObject(obj, false);
3929642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      return;
3939642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    }
3949642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  }
3959642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier
3969642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  DCHECK(object_bitmap->HasAddress(obj));
3979642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  object_bitmap->Clear(obj);
3989642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier}
3999642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier
4009642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartierinline void MarkSweep::MarkObjectNonNull(const Object* obj) {
40169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(obj != NULL);
402b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
4039642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  if (IsImmune(obj)) {
404e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    DCHECK(IsMarked(obj));
405357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    return;
406357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
407357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
408b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  // Try to take advantage of locality of references within a space, failing this find the space
409b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  // the hard way.
4101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* object_bitmap = current_mark_bitmap_;
41102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (UNLIKELY(!object_bitmap->HasAddress(obj))) {
4121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    accounting::SpaceBitmap* new_bitmap = heap_->GetMarkBitmap()->GetContinuousSpaceBitmap(obj);
4131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (LIKELY(new_bitmap != NULL)) {
41402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      object_bitmap = new_bitmap;
415e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    } else {
4169642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      MarkLargeObject(obj, true);
417e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier      return;
418357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
419b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  }
420b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
42169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // This object was not previously marked.
42202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (!object_bitmap->Test(obj)) {
42302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    object_bitmap->Set(obj);
424ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    // Lock is not needed but is here anyways to please annotalysis.
425ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier    MutexLock mu(Thread::Current(), mark_stack_lock_);
426184e322fe8ddd75c844a1eb2eb1ca32bc02f2d45Mathieu Chartier    if (UNLIKELY(mark_stack_->Size() >= mark_stack_->Capacity())) {
427184e322fe8ddd75c844a1eb2eb1ca32bc02f2d45Mathieu Chartier      ExpandMarkStack();
42869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
429184e322fe8ddd75c844a1eb2eb1ca32bc02f2d45Mathieu Chartier    // The object must be pushed on to the mark stack.
430184e322fe8ddd75c844a1eb2eb1ca32bc02f2d45Mathieu Chartier    mark_stack_->PushBack(const_cast<Object*>(obj));
43169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
43269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
43369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
43402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier// Rare case, probably not worth inlining since it will increase instruction cache miss rate.
4359642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartierbool MarkSweep::MarkLargeObject(const Object* obj, bool set) {
4361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // TODO: support >1 discontinuous space.
4371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
4381d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceSetMap* large_objects = large_object_space->GetMarkObjects();
43902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (kProfileLargeObjects) {
44002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    ++large_object_test_;
44102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
44202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (UNLIKELY(!large_objects->Test(obj))) {
4434fcb8d335cc856380531a42c8c708cc789a77395Mathieu Chartier    if (!large_object_space->Contains(obj)) {
44402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      LOG(ERROR) << "Tried to mark " << obj << " not contained by any spaces";
44502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      LOG(ERROR) << "Attempting see if it's a bad root";
44602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      VerifyRoots();
44702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      LOG(FATAL) << "Can't mark bad root";
44802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    }
44902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    if (kProfileLargeObjects) {
45002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      ++large_object_mark_;
45102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    }
4529642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    if (set) {
4539642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      large_objects->Set(obj);
4549642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    } else {
4559642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      large_objects->Clear(obj);
4569642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    }
45702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    return true;
45802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
45902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  return false;
46002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}
46102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
46202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierinline bool MarkSweep::MarkObjectParallel(const Object* obj) {
46302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  DCHECK(obj != NULL);
46402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
4659642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  if (IsImmune(obj)) {
46602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    DCHECK(IsMarked(obj));
46702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    return false;
46802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
46902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
47002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // Try to take advantage of locality of references within a space, failing this find the space
47102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // the hard way.
4721d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* object_bitmap = current_mark_bitmap_;
47302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (UNLIKELY(!object_bitmap->HasAddress(obj))) {
4741d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    accounting::SpaceBitmap* new_bitmap = heap_->GetMarkBitmap()->GetContinuousSpaceBitmap(obj);
47502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    if (new_bitmap != NULL) {
47602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      object_bitmap = new_bitmap;
47702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    } else {
47802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      // TODO: Remove the Thread::Current here?
47902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      // TODO: Convert this to some kind of atomic marking?
48002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier      MutexLock mu(Thread::Current(), large_object_lock_);
4819642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier      return MarkLargeObject(obj, true);
48202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    }
48302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
48402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
48502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // Return true if the object was not previously marked.
48602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  return !object_bitmap->AtomicTestAndSet(obj);
48702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}
48802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
48969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Used to mark objects when recursing.  Recursion is done by moving
49069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// the finger across the bitmaps in address order and marking child
49169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// objects.  Any newly-marked objects whose addresses are lower than
49269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// the finger won't be visited by the bitmap scan, so those objects
49369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// need to be added to the mark stack.
49494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierinline void MarkSweep::MarkObject(const Object* obj) {
49569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  if (obj != NULL) {
4969642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    MarkObjectNonNull(obj);
49769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
49869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
49969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
5002b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::MarkRoot(const Object* obj) {
5012b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  if (obj != NULL) {
5029642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier    MarkObjectNonNull(obj);
5032b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  }
5042b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier}
5052b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
506423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu ChartierObject* MarkSweep::MarkRootParallelCallback(Object* root, void* arg) {
507ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  DCHECK(root != NULL);
508ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier  DCHECK(arg != NULL);
509ba311b4385fa3f382f01312a8cc97b52011232e3Mathieu Chartier  reinterpret_cast<MarkSweep*>(arg)->MarkObjectNonNullParallel(root);
510423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  return root;
511ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier}
512ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier
513423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu ChartierObject* MarkSweep::MarkRootCallback(Object* root, void* arg) {
514423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  DCHECK(root != nullptr);
515423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  DCHECK(arg != nullptr);
516423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  reinterpret_cast<MarkSweep*>(arg)->MarkObjectNonNull(root);
517423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  return root;
518262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier}
519262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier
5206f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartiervoid MarkSweep::VerifyRootCallback(const Object* root, void* arg, size_t vreg,
52140e3bacfd57bca2ca39c1caec64680bd0ed4a16dIan Rogers                                   const StackVisitor* visitor) {
52240e3bacfd57bca2ca39c1caec64680bd0ed4a16dIan Rogers  reinterpret_cast<MarkSweep*>(arg)->VerifyRoot(root, vreg, visitor);
5236f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier}
5246f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier
52540e3bacfd57bca2ca39c1caec64680bd0ed4a16dIan Rogersvoid MarkSweep::VerifyRoot(const Object* root, size_t vreg, const StackVisitor* visitor) {
5266f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier  // See if the root is on any space bitmap.
5271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (GetHeap()->GetLiveBitmap()->GetContinuousSpaceBitmap(root) == NULL) {
5281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
5294202b7484dab71ca4dfc2109ebb3fd04b87badfbMathieu Chartier    if (!large_object_space->Contains(root)) {
5306f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier      LOG(ERROR) << "Found invalid root: " << root;
53140e3bacfd57bca2ca39c1caec64680bd0ed4a16dIan Rogers      if (visitor != NULL) {
53240e3bacfd57bca2ca39c1caec64680bd0ed4a16dIan Rogers        LOG(ERROR) << visitor->DescribeLocation() << " in VReg: " << vreg;
5336f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier      }
5346f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier    }
5356f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier  }
5366f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier}
5376f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier
5386f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartiervoid MarkSweep::VerifyRoots() {
5396f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier  Runtime::Current()->GetThreadList()->VerifyRoots(VerifyRootCallback, this);
5406f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier}
5416f1c94968ada57da433debf8e2d1b38a80ceb510Mathieu Chartier
54269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Marks all objects in the root set.
54369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapirovoid MarkSweep::MarkRoots() {
5444446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("MarkRoots");
545423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  Runtime::Current()->VisitNonConcurrentRoots(MarkRootCallback, this);
5464446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
5479ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier}
5489ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartier
549858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartiervoid MarkSweep::MarkNonThreadRoots() {
5504446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("MarkNonThreadRoots");
551423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  Runtime::Current()->VisitNonThreadRoots(MarkRootCallback, this);
5524446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
553858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier}
554858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
5559ebae1f30b84dfd8dab4144f80eebec4f8fc8851Mathieu Chartiervoid MarkSweep::MarkConcurrentRoots() {
5564446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("MarkConcurrentRoots");
5571d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // Visit all runtime roots and clear dirty flags.
558423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  Runtime::Current()->VisitConcurrentRoots(MarkRootCallback, this, false, true);
5594446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
56069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
56169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
562b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartiervoid MarkSweep::CheckObject(const Object* obj) {
563b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  DCHECK(obj != NULL);
56494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  VisitObjectReferences(obj, [this](const Object* obj, const Object* ref, MemberOffset offset,
56594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      bool is_static) NO_THREAD_SAFETY_ANALYSIS {
56694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
56794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    CheckReference(obj, ref, offset, is_static);
56894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  });
569b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier}
570b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier
571b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartiervoid MarkSweep::VerifyImageRootVisitor(Object* root, void* arg) {
572b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  DCHECK(root != NULL);
573b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  DCHECK(arg != NULL);
574b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  MarkSweep* mark_sweep = reinterpret_cast<MarkSweep*>(arg);
575b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  DCHECK(mark_sweep->heap_->GetMarkBitmap()->Test(root));
576b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  mark_sweep->CheckObject(root);
577b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier}
578b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier
5791d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::BindLiveToMarkBitmap(space::ContinuousSpace* space) {
5801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK(space->IsDlMallocSpace());
5811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::DlMallocSpace* alloc_space = space->AsDlMallocSpace();
5821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
5831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* mark_bitmap = alloc_space->mark_bitmap_.release();
5847469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  GetHeap()->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap);
5857469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  alloc_space->temp_bitmap_.reset(mark_bitmap);
5867469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  alloc_space->mark_bitmap_.reset(live_bitmap);
5877469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
5887469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
58902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass ScanObjectVisitor {
590cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier public:
59194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  explicit ScanObjectVisitor(MarkSweep* const mark_sweep) ALWAYS_INLINE
59294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      : mark_sweep_(mark_sweep) {}
593cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
5942b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // TODO: Fixme when anotatalysis works with visitors.
59594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  void operator()(const Object* obj) const ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS {
59694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (kCheckLocks) {
5972b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
5982b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
5992b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    }
60002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    mark_sweep_->ScanObject(obj);
601cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  }
602cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
603cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier private:
604cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  MarkSweep* const mark_sweep_;
605cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier};
606cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
60794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiertemplate <bool kUseFinger = false>
60894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierclass MarkStackTask : public Task {
60994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier public:
61094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  MarkStackTask(ThreadPool* thread_pool, MarkSweep* mark_sweep, size_t mark_stack_size,
61194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                const Object** mark_stack)
61294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      : mark_sweep_(mark_sweep),
61394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        thread_pool_(thread_pool),
61494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        mark_stack_pos_(mark_stack_size) {
61594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // We may have to copy part of an existing mark stack when another mark stack overflows.
61694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (mark_stack_size != 0) {
61794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      DCHECK(mark_stack != NULL);
61894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // TODO: Check performance?
61994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      std::copy(mark_stack, mark_stack + mark_stack_size, mark_stack_);
62094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
62194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (kCountTasks) {
62294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      ++mark_sweep_->work_chunks_created_;
6231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    }
624262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier  }
625262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier
62694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  static const size_t kMaxSize = 1 * KB;
627cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
62894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier protected:
62994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  class ScanObjectParallelVisitor {
63094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier   public:
63194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    explicit ScanObjectParallelVisitor(MarkStackTask<kUseFinger>* chunk_task) ALWAYS_INLINE
63294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        : chunk_task_(chunk_task) {}
63394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
63494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    void operator()(const Object* obj) const {
63594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      MarkSweep* mark_sweep = chunk_task_->mark_sweep_;
63694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      mark_sweep->ScanObjectVisit(obj,
63794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          [mark_sweep, this](const Object* /* obj */, const Object* ref,
63894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier              const MemberOffset& /* offset */, bool /* is_static */) ALWAYS_INLINE {
63994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (ref != nullptr && mark_sweep->MarkObjectParallel(ref)) {
64094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          if (kUseFinger) {
64194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            android_memory_barrier();
64294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            if (reinterpret_cast<uintptr_t>(ref) >=
64394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                static_cast<uintptr_t>(mark_sweep->atomic_finger_)) {
64494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier              return;
64594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            }
64694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          }
64794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          chunk_task_->MarkStackPush(ref);
64894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
64994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      });
65094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
65194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
65294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier   private:
65394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    MarkStackTask<kUseFinger>* const chunk_task_;
65494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  };
65594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
65694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual ~MarkStackTask() {
65794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Make sure that we have cleared our mark stack.
65894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    DCHECK_EQ(mark_stack_pos_, 0U);
65994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (kCountTasks) {
66094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      ++mark_sweep_->work_chunks_deleted_;
6612b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    }
662cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  }
663cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
66494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  MarkSweep* const mark_sweep_;
66594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ThreadPool* const thread_pool_;
66694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Thread local mark stack for this task.
66794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  const Object* mark_stack_[kMaxSize];
66894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Mark stack position.
66994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  size_t mark_stack_pos_;
67094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
67194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  void MarkStackPush(const Object* obj) ALWAYS_INLINE {
67294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (UNLIKELY(mark_stack_pos_ == kMaxSize)) {
67394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // Mark stack overflow, give 1/2 the stack to the thread pool as a new work task.
67494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      mark_stack_pos_ /= 2;
67594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      auto* task = new MarkStackTask(thread_pool_, mark_sweep_, kMaxSize - mark_stack_pos_,
67694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                     mark_stack_ + mark_stack_pos_);
67794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      thread_pool_->AddTask(Thread::Current(), task);
67894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
67994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    DCHECK(obj != nullptr);
68094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    DCHECK(mark_stack_pos_ < kMaxSize);
68194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    mark_stack_[mark_stack_pos_++] = obj;
68294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
68394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
68494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Finalize() {
68594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    delete this;
68694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
68794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
68894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Scans all of the objects
68994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Run(Thread* self) {
69094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ScanObjectParallelVisitor visitor(this);
69194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // TODO: Tune this.
69294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    static const size_t kFifoSize = 4;
69394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    BoundedFifoPowerOfTwo<const Object*, kFifoSize> prefetch_fifo;
69494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    for (;;) {
69594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      const Object* obj = NULL;
69694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      if (kUseMarkStackPrefetch) {
69794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        while (mark_stack_pos_ != 0 && prefetch_fifo.size() < kFifoSize) {
69894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          const Object* obj = mark_stack_[--mark_stack_pos_];
69994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          DCHECK(obj != NULL);
70094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          __builtin_prefetch(obj);
70194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          prefetch_fifo.push_back(obj);
70294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
70394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (UNLIKELY(prefetch_fifo.empty())) {
70494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
70594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
70694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        obj = prefetch_fifo.front();
70794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        prefetch_fifo.pop_front();
70894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      } else {
70994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (UNLIKELY(mark_stack_pos_ == 0)) {
71094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
71194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
71294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        obj = mark_stack_[--mark_stack_pos_];
71394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      }
71494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      DCHECK(obj != NULL);
71594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      visitor(obj);
71694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
71794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
71894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier};
71994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
72094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierclass CardScanTask : public MarkStackTask<false> {
72194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier public:
72294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  CardScanTask(ThreadPool* thread_pool, MarkSweep* mark_sweep, accounting::SpaceBitmap* bitmap,
72394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier               byte* begin, byte* end, byte minimum_age, size_t mark_stack_size,
72494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier               const Object** mark_stack_obj)
72594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      : MarkStackTask<false>(thread_pool, mark_sweep, mark_stack_size, mark_stack_obj),
72694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        bitmap_(bitmap),
72794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        begin_(begin),
72894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        end_(end),
72994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        minimum_age_(minimum_age) {
73094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
73194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
73294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier protected:
73394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  accounting::SpaceBitmap* const bitmap_;
73494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  byte* const begin_;
73594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  byte* const end_;
73694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  const byte minimum_age_;
73794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
73894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Finalize() {
73994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    delete this;
74094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
74194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
74294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Run(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
74394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ScanObjectParallelVisitor visitor(this);
74494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    accounting::CardTable* card_table = mark_sweep_->GetHeap()->GetCardTable();
74594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    card_table->Scan(bitmap_, begin_, end_, visitor, minimum_age_);
74694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Finish by emptying our local mark stack.
74794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    MarkStackTask::Run(self);
74894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
749cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier};
750cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
7512775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartiersize_t MarkSweep::GetThreadCount(bool paused) const {
7522775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  if (heap_->GetThreadPool() == nullptr || !heap_->CareAboutPauseTimes()) {
7532775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    return 0;
7542775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  }
7552775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  if (paused) {
7562775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    return heap_->GetParallelGCThreadCount() + 1;
7572775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  } else {
7582775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    return heap_->GetConcGCThreadCount() + 1;
7592775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  }
7602775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier}
7612775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier
76294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiervoid MarkSweep::ScanGrayObjects(bool paused, byte minimum_age) {
76394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  accounting::CardTable* card_table = GetHeap()->GetCardTable();
76494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ThreadPool* thread_pool = GetHeap()->GetThreadPool();
7652775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  size_t thread_count = GetThreadCount(paused);
7662775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  // The parallel version with only one thread is faster for card scanning, TODO: fix.
7672775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  if (kParallelCardScan && thread_count > 0) {
768720ef7680573c1afd12f99f02eee3045daee5168Mathieu Chartier    Thread* self = Thread::Current();
76994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Can't have a different split for each space since multiple spaces can have their cards being
77094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // scanned at the same time.
77194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    timings_.StartSplit(paused ? "(Paused)ScanGrayObjects" : "ScanGrayObjects");
77294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Try to take some of the mark stack since we can pass this off to the worker tasks.
77394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const Object** mark_stack_begin = const_cast<const Object**>(mark_stack_->Begin());
77494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const Object** mark_stack_end = const_cast<const Object**>(mark_stack_->End());
775720ef7680573c1afd12f99f02eee3045daee5168Mathieu Chartier    const size_t mark_stack_size = mark_stack_end - mark_stack_begin;
77694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Estimated number of work tasks we will create.
77794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const size_t mark_stack_tasks = GetHeap()->GetContinuousSpaces().size() * thread_count;
77894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    DCHECK_NE(mark_stack_tasks, 0U);
77994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const size_t mark_stack_delta = std::min(CardScanTask::kMaxSize / 2,
78094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                             mark_stack_size / mark_stack_tasks + 1);
78194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
78294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      byte* card_begin = space->Begin();
78394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      byte* card_end = space->End();
78494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // Calculate how many bytes of heap we will scan,
78594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      const size_t address_range = card_end - card_begin;
78694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // Calculate how much address range each task gets.
78794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      const size_t card_delta = RoundUp(address_range / thread_count + 1,
78894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                        accounting::CardTable::kCardSize);
78994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // Create the worker tasks for this space.
79094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      while (card_begin != card_end) {
79194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        // Add a range of cards.
79294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        size_t addr_remaining = card_end - card_begin;
79394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        size_t card_increment = std::min(card_delta, addr_remaining);
79494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        // Take from the back of the mark stack.
79594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        size_t mark_stack_remaining = mark_stack_end - mark_stack_begin;
79694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        size_t mark_stack_increment = std::min(mark_stack_delta, mark_stack_remaining);
79794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        mark_stack_end -= mark_stack_increment;
79894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        mark_stack_->PopBackCount(static_cast<int32_t>(mark_stack_increment));
79994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        DCHECK_EQ(mark_stack_end, mark_stack_->End());
80094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        // Add the new task to the thread pool.
80194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        auto* task = new CardScanTask(thread_pool, this, space->GetMarkBitmap(), card_begin,
80294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                      card_begin + card_increment, minimum_age,
80394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                      mark_stack_increment, mark_stack_end);
80494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        thread_pool->AddTask(self, task);
80594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        card_begin += card_increment;
80694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      }
80794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
8082775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    thread_pool->SetMaxActiveWorkers(thread_count - 1);
80994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    thread_pool->StartWorkers(self);
8102775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    thread_pool->Wait(self, true, true);
81194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    thread_pool->StopWorkers(self);
81294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    timings_.EndSplit();
81394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  } else {
81494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
81594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      // Image spaces are handled properly since live == marked for them.
81694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      switch (space->GetGcRetentionPolicy()) {
81794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        case space::kGcRetentionPolicyNeverCollect:
81894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          timings_.StartSplit(paused ? "(Paused)ScanGrayImageSpaceObjects" :
81994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier              "ScanGrayImageSpaceObjects");
82094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
82194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        case space::kGcRetentionPolicyFullCollect:
82294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          timings_.StartSplit(paused ? "(Paused)ScanGrayZygoteSpaceObjects" :
82394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier              "ScanGrayZygoteSpaceObjects");
82494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
82594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        case space::kGcRetentionPolicyAlwaysCollect:
82694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          timings_.StartSplit(paused ? "(Paused)ScanGrayAllocSpaceObjects" :
82794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier              "ScanGrayAllocSpaceObjects");
82894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
82994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
83094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      ScanObjectVisitor visitor(this);
83194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      card_table->Scan(space->GetMarkBitmap(), space->Begin(), space->End(), visitor, minimum_age);
83294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      timings_.EndSplit();
83394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
83494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
83594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier}
83694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
837262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartiervoid MarkSweep::VerifyImageRoots() {
838262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier  // Verify roots ensures that all the references inside the image space point
839262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier  // objects which are either in the image space or marked objects in the alloc
840262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier  // space
8414446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("VerifyImageRoots");
84202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
84302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    if (space->IsImageSpace()) {
84402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      space::ImageSpace* image_space = space->AsImageSpace();
84502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      uintptr_t begin = reinterpret_cast<uintptr_t>(image_space->Begin());
84602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      uintptr_t end = reinterpret_cast<uintptr_t>(image_space->End());
84702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      accounting::SpaceBitmap* live_bitmap = image_space->GetLiveBitmap();
848b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier      DCHECK(live_bitmap != NULL);
84994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      live_bitmap->VisitMarkedRange(begin, end, [this](const Object* obj) {
85094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (kCheckLocks) {
85194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
85294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
85394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        DCHECK(obj != NULL);
85494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        CheckObject(obj);
85594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      });
856262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier    }
857262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier  }
8584446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
859262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier}
860262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier
86194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartierclass RecursiveMarkTask : public MarkStackTask<false> {
86294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier public:
86394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  RecursiveMarkTask(ThreadPool* thread_pool, MarkSweep* mark_sweep,
86494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                    accounting::SpaceBitmap* bitmap, uintptr_t begin, uintptr_t end)
86594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      : MarkStackTask<false>(thread_pool, mark_sweep, 0, NULL),
86694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        bitmap_(bitmap),
86794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        begin_(begin),
86894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        end_(end) {
86994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
87094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
87194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier protected:
87294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  accounting::SpaceBitmap* const bitmap_;
87394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  const uintptr_t begin_;
87494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  const uintptr_t end_;
87594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
87694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Finalize() {
87794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    delete this;
87894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
87994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
88094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Scans all of the objects
88194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  virtual void Run(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
88294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ScanObjectParallelVisitor visitor(this);
88394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    bitmap_->VisitMarkedRange(begin_, end_, visitor);
88494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // Finish by emptying our local mark stack.
88594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    MarkStackTask::Run(self);
88694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  }
88794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier};
88894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
88958551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro// Populates the mark stack based on the set of marked objects and
89058551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro// recursively marks until the mark stack is emptied.
8912b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::RecursiveMark() {
8924654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("RecursiveMark", &timings_);
8931f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  // RecursiveMark will build the lists of known instances of the Reference classes.
8941f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  // See DelayReferenceReferent for details.
8951f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  CHECK(soft_reference_list_ == NULL);
8961f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  CHECK(weak_reference_list_ == NULL);
8971f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  CHECK(finalizer_reference_list_ == NULL);
8981f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  CHECK(phantom_reference_list_ == NULL);
8991f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  CHECK(cleared_reference_list_ == NULL);
9001f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom
90194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  if (kUseRecursiveMark) {
90294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const bool partial = GetGcType() == kGcTypePartial;
90394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ScanObjectVisitor scan_visitor(this);
90494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    auto* self = Thread::Current();
90594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ThreadPool* thread_pool = heap_->GetThreadPool();
9062775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    size_t thread_count = GetThreadCount(false);
9072775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    const bool parallel = kParallelRecursiveMark && thread_count > 1;
90894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    mark_stack_->Reset();
90902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
9101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      if ((space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect) ||
9111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers          (!partial && space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect)) {
9122b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier        current_mark_bitmap_ = space->GetMarkBitmap();
9132b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier        if (current_mark_bitmap_ == NULL) {
9142b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier          GetHeap()->DumpSpaces();
9152b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier          LOG(FATAL) << "invalid bitmap";
9162b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier        }
91794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (parallel) {
91894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          // We will use the mark stack the future.
91994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          // CHECK(mark_stack_->IsEmpty());
92094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          // This function does not handle heap end increasing, so we must use the space end.
92194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          uintptr_t begin = reinterpret_cast<uintptr_t>(space->Begin());
92294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          uintptr_t end = reinterpret_cast<uintptr_t>(space->End());
92394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          atomic_finger_ = static_cast<int32_t>(0xFFFFFFFF);
92494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier
92594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          // Create a few worker tasks.
9262775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          const size_t n = thread_count * 2;
92794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          while (begin != end) {
92894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            uintptr_t start = begin;
92994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            uintptr_t delta = (end - begin) / n;
93094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            delta = RoundUp(delta, KB);
93194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            if (delta < 16 * KB) delta = end - begin;
93294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            begin += delta;
93394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            auto* task = new RecursiveMarkTask(thread_pool, this, current_mark_bitmap_, start,
93494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                               begin);
93594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier            thread_pool->AddTask(self, task);
93694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          }
9372775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          thread_pool->SetMaxActiveWorkers(thread_count - 1);
93894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          thread_pool->StartWorkers(self);
9392775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier          thread_pool->Wait(self, true, true);
94094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          thread_pool->StopWorkers(self);
94194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        } else {
94294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          // This function does not handle heap end increasing, so we must use the space end.
94394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          uintptr_t begin = reinterpret_cast<uintptr_t>(space->Begin());
94494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          uintptr_t end = reinterpret_cast<uintptr_t>(space->End());
94594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          current_mark_bitmap_->VisitMarkedRange(begin, end, scan_visitor);
94694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
947357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier      }
948357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
949357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
95094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ProcessMarkStack(false);
95158551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro}
95258551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
9536aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartiermirror::Object* MarkSweep::SystemWeakIsMarkedCallback(Object* object, void* arg) {
9545712d5d04640925970db9c98938ffaf806b3962cMathieu Chartier  if (reinterpret_cast<MarkSweep*>(arg)->IsMarked(object)) {
9556aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier    return object;
9566aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  }
9576aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  return nullptr;
958357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier}
959357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
96094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiervoid MarkSweep::RecursiveMarkDirtyObjects(bool paused, byte minimum_age) {
96194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ScanGrayObjects(paused, minimum_age);
96294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ProcessMarkStack(paused);
963262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier}
964262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier
96558551df3c2646ed507feec9e9eb3768085a76059Carl Shapirovoid MarkSweep::ReMarkRoots() {
9664446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("ReMarkRoots");
967423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  Runtime::Current()->VisitRoots(MarkRootCallback, this, true, true);
9684446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
96958551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro}
97058551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
9717469ebf3888b8037421cb6834f37f946646265ecMathieu Chartierstruct ArrayMarkedCheck {
9721d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::ObjectStack* live_stack;
9737469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  MarkSweep* mark_sweep;
9747469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier};
9757469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
9767469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier// Either marked or not live.
9776aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartiermirror::Object* MarkSweep::SystemWeakIsMarkedArrayCallback(Object* object, void* arg) {
9787469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  ArrayMarkedCheck* array_check = reinterpret_cast<ArrayMarkedCheck*>(arg);
9797469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  if (array_check->mark_sweep->IsMarked(object)) {
9806aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier    return object;
9817469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  }
9821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::ObjectStack* live_stack = array_check->live_stack;
9836aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  if (std::find(live_stack->Begin(), live_stack->End(), object) == live_stack->End()) {
9846aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier    return object;
9856aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  }
9866aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  return nullptr;
9877469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
9887469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
9891d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::SweepSystemWeaksArray(accounting::ObjectStack* allocations) {
99046a23638436afdf17330870ef150f5b8eb66410cMathieu Chartier  Runtime* runtime = Runtime::Current();
991357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // The callbacks check
992357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // !is_marked where is_marked is the callback but we want
993357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // !IsMarked && IsLive
994357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // So compute !(!IsMarked && IsLive) which is equal to (IsMarked || !IsLive).
995357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // Or for swapped (IsLive || !IsMarked).
9964446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("SweepSystemWeaksArray");
9977469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  ArrayMarkedCheck visitor;
9987469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  visitor.live_stack = allocations;
9997469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  visitor.mark_sweep = this;
10006aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  runtime->SweepSystemWeaks(SystemWeakIsMarkedArrayCallback, &visitor);
10014446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
10027469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
10037469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
10047469ebf3888b8037421cb6834f37f946646265ecMathieu Chartiervoid MarkSweep::SweepSystemWeaks() {
10057469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  Runtime* runtime = Runtime::Current();
10067469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  // The callbacks check
10077469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  // !is_marked where is_marked is the callback but we want
10087469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  // !IsMarked && IsLive
10097469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  // So compute !(!IsMarked && IsLive) which is equal to (IsMarked || !IsLive).
10107469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  // Or for swapped (IsLive || !IsMarked).
10114446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("SweepSystemWeaks");
10126aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  runtime->SweepSystemWeaks(SystemWeakIsMarkedCallback, this);
10134446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
101469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
101569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
10166aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartiermirror::Object* MarkSweep::VerifySystemWeakIsLiveCallback(Object* obj, void* arg) {
1017c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier  reinterpret_cast<MarkSweep*>(arg)->VerifyIsLive(obj);
1018c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier  // We don't actually want to sweep the object, so lets return "marked"
10196aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  return obj;
1020c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier}
1021c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier
1022c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartiervoid MarkSweep::VerifyIsLive(const Object* obj) {
1023c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier  Heap* heap = GetHeap();
1024c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier  if (!heap->GetLiveBitmap()->Test(obj)) {
10251d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
10267469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier    if (!large_object_space->GetLiveObjects()->Test(obj)) {
10277469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      if (std::find(heap->allocation_stack_->Begin(), heap->allocation_stack_->End(), obj) ==
10287469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier          heap->allocation_stack_->End()) {
10297469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        // Object not found!
10307469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        heap->DumpSpaces();
10317469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        LOG(FATAL) << "Found dead object " << obj;
10327469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      }
1033c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier    }
1034c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier  }
1035c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier}
1036c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier
1037c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartiervoid MarkSweep::VerifySystemWeaks() {
10386aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  // Verify system weaks, uses a special object visitor which returns the input object.
10396aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier  Runtime::Current()->SweepSystemWeaks(VerifySystemWeakIsLiveCallback, this);
1040c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier}
1041c7b83a0d8ac73bdfff751619ae2a34948e3534b7Mathieu Chartier
1042b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughesstruct SweepCallbackContext {
1043357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  MarkSweep* mark_sweep;
10441d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::AllocSpace* space;
104550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self;
1046b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes};
1047b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
10480e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartierclass CheckpointMarkThreadRoots : public Closure {
1049858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier public:
105093ba893c20532990a430741e0a97212900094e8cBrian Carlstrom  explicit CheckpointMarkThreadRoots(MarkSweep* mark_sweep) : mark_sweep_(mark_sweep) {}
1051858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
1052858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  virtual void Run(Thread* thread) NO_THREAD_SAFETY_ANALYSIS {
10533f9667022788ba1effcd1e47fc9e3decc4db569dMathieu Chartier    ATRACE_BEGIN("Marking thread roots");
1054858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier    // Note: self is not necessarily equal to thread since thread may be suspended.
1055858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier    Thread* self = Thread::Current();
1056d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    CHECK(thread == self || thread->IsSuspended() || thread->GetState() == kWaitingPerformingGc)
1057d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier        << thread->GetState() << " thread " << thread << " self " << self;
1058ac86a7cad60c20a131011338057887bb64cbfd38Mathieu Chartier    thread->VisitRoots(MarkSweep::MarkRootParallelCallback, mark_sweep_);
10593f9667022788ba1effcd1e47fc9e3decc4db569dMathieu Chartier    ATRACE_END();
1060858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier    mark_sweep_->GetBarrier().Pass(self);
1061858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  }
1062858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
1063858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier private:
1064858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  MarkSweep* mark_sweep_;
1065858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier};
1066858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
10671d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::MarkRootsCheckpoint(Thread* self) {
1068d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier  CheckpointMarkThreadRoots check_point(this);
10694446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("MarkRootsCheckpoint");
1070858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier  ThreadList* thread_list = Runtime::Current()->GetThreadList();
10711d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // Request the check point is run on all threads returning a count of the threads that must
10721d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // run through the barrier including self.
10731d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  size_t barrier_count = thread_list->RunCheckpoint(&check_point);
10741d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // Release locks then wait for all mutator threads to pass the barrier.
10751d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // TODO: optimize to not release locks when there are no threads to wait for.
10761d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Locks::heap_bitmap_lock_->ExclusiveUnlock(self);
10771d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Locks::mutator_lock_->SharedUnlock(self);
10781d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  ThreadState old_state = self->SetState(kWaitingForCheckPointsToRun);
10791d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK_EQ(old_state, kWaitingPerformingGc);
10801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc_barrier_->Increment(self, barrier_count);
10811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  self->SetState(kWaitingPerformingGc);
10821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Locks::mutator_lock_->SharedLock(self);
10831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Locks::heap_bitmap_lock_->ExclusiveLock(self);
10844446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
1085858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier}
1086858f1c5fd5e528d0b16040ced74d4636046a42d8Mathieu Chartier
108730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogersvoid MarkSweep::SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) {
1088b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg);
1089357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  MarkSweep* mark_sweep = context->mark_sweep;
1090357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  Heap* heap = mark_sweep->GetHeap();
10911d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::AllocSpace* space = context->space;
109250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = context->self;
109350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Locks::heap_bitmap_lock_->AssertExclusiveHeld(self);
10945d76c435082332ef79a22962386fa92a0870e378Ian Rogers  // Use a bulk free, that merges consecutive objects before freeing or free per object?
10955d76c435082332ef79a22962386fa92a0870e378Ian Rogers  // Documentation suggests better free performance with merging, but this may be at the expensive
10965d76c435082332ef79a22962386fa92a0870e378Ian Rogers  // of allocation.
109702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  size_t freed_objects = num_ptrs;
109802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // AllocSpace::FreeList clears the value in ptrs, so perform after clearing the live bit
109902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  size_t freed_bytes = space->FreeList(self, num_ptrs, ptrs);
110000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  heap->RecordFree(freed_objects, freed_bytes);
11014b95e8fad803ad307fa09c11c08894544e07a731Mathieu Chartier  mark_sweep->freed_objects_.fetch_add(freed_objects);
11024b95e8fad803ad307fa09c11c08894544e07a731Mathieu Chartier  mark_sweep->freed_bytes_.fetch_add(freed_bytes);
110358551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro}
110458551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
1105cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartiervoid MarkSweep::ZygoteSweepCallback(size_t num_ptrs, Object** ptrs, void* arg) {
1106cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg);
110750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Locks::heap_bitmap_lock_->AssertExclusiveHeld(context->self);
1108357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  Heap* heap = context->mark_sweep->GetHeap();
1109cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  // We don't free any actual memory to avoid dirtying the shared zygote pages.
1110cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  for (size_t i = 0; i < num_ptrs; ++i) {
1111cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier    Object* obj = static_cast<Object*>(ptrs[i]);
1112cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier    heap->GetLiveBitmap()->Clear(obj);
1113cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier    heap->GetCardTable()->MarkCard(obj);
1114cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier  }
1115cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier}
1116cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier
11171d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::SweepArray(accounting::ObjectStack* allocations, bool swap_bitmaps) {
11181d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::DlMallocSpace* space = heap_->GetAllocSpace();
1119357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
112094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  timings_.StartSplit("SweepArray");
1121357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // Newly allocated objects MUST be in the alloc space and those are the only objects which we are
1122357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // going to free.
11231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
11241d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
11251d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
11261d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceSetMap* large_live_objects = large_object_space->GetLiveObjects();
11271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceSetMap* large_mark_objects = large_object_space->GetMarkObjects();
1128357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  if (swap_bitmaps) {
1129357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    std::swap(live_bitmap, mark_bitmap);
1130e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    std::swap(large_live_objects, large_mark_objects);
1131357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
1132357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
1133e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  size_t freed_bytes = 0;
1134e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  size_t freed_large_object_bytes = 0;
1135b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  size_t freed_objects = 0;
1136e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  size_t freed_large_objects = 0;
1137357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  size_t count = allocations->Size();
1138d8195f19840911a73b1491dfc8e7c18139753731Mathieu Chartier  Object** objects = const_cast<Object**>(allocations->Begin());
1139357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  Object** out = objects;
1140b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  Object** objects_to_chunk_free = out;
1141357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
1142357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  // Empty the allocation stack.
114350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
114402c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom  for (size_t i = 0; i < count; ++i) {
1145357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    Object* obj = objects[i];
1146e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    // There should only be objects in the AllocSpace/LargeObjectSpace in the allocation stack.
1147e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    if (LIKELY(mark_bitmap->HasAddress(obj))) {
1148e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier      if (!mark_bitmap->Test(obj)) {
1149e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier        // Don't bother un-marking since we clear the mark bitmap anyways.
1150e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier        *(out++) = obj;
1151b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi        // Free objects in chunks.
1152b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi        DCHECK_GE(out, objects_to_chunk_free);
1153b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi        DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
1154b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi        if (static_cast<size_t>(out - objects_to_chunk_free) == kSweepArrayChunkFreeSize) {
1155e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier          timings_.StartSplit("FreeList");
1156b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi          size_t chunk_freed_objects = out - objects_to_chunk_free;
1157b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi          freed_objects += chunk_freed_objects;
1158b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi          freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
1159b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi          objects_to_chunk_free = out;
1160e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier          timings_.EndSplit();
1161b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi        }
1162e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier      }
1163e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    } else if (!large_mark_objects->Test(obj)) {
1164e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier      ++freed_large_objects;
1165e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier      freed_large_object_bytes += large_object_space->Free(self, obj);
1166357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
1167357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
1168b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  // Free the remaining objects in chunks.
1169b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  DCHECK_GE(out, objects_to_chunk_free);
1170b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
1171b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  if (out - objects_to_chunk_free > 0) {
1172e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier    timings_.StartSplit("FreeList");
1173b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi    size_t chunk_freed_objects = out - objects_to_chunk_free;
1174b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi    freed_objects += chunk_freed_objects;
1175b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi    freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
1176e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier    timings_.EndSplit();
1177b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  }
11781d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK_EQ(count, allocations->Size());
11794446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
1180357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
1181b22a451675c29ac3fc82a8761d2a385a170d6d7fHiroshi Yamauchi  timings_.StartSplit("RecordFree");
118240e978b0bb5e0011a69d7d1fb83a3e59f2df4f84Mathieu Chartier  VLOG(heap) << "Freed " << freed_objects << "/" << count
1183e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier             << " objects with size " << PrettySize(freed_bytes);
1184e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  heap_->RecordFree(freed_objects + freed_large_objects, freed_bytes + freed_large_object_bytes);
11854b95e8fad803ad307fa09c11c08894544e07a731Mathieu Chartier  freed_objects_.fetch_add(freed_objects);
1186e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_objects_.fetch_add(freed_large_objects);
11874b95e8fad803ad307fa09c11c08894544e07a731Mathieu Chartier  freed_bytes_.fetch_add(freed_bytes);
1188e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_object_bytes_.fetch_add(freed_large_object_bytes);
11894446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
11901d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
11914446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("ResetStack");
1192357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  allocations->Reset();
11934446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
1194357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier}
1195357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
11961d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid MarkSweep::Sweep(bool swap_bitmaps) {
1197b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  DCHECK(mark_stack_->IsEmpty());
11984654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit("Sweep", &timings_);
1199b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier
12001d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  const bool partial = (GetGcType() == kGcTypePartial);
1201b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  SweepCallbackContext scc;
1202357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  scc.mark_sweep = this;
120350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  scc.self = Thread::Current();
120402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
12051d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // We always sweep always collect spaces.
12061d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    bool sweep_space = (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect);
12071d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (!partial && !sweep_space) {
12081d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      // We sweep full collect spaces when the GC isn't a partial GC (ie its full).
12091d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      sweep_space = (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect);
12101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    }
12111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (sweep_space) {
1212720ef7680573c1afd12f99f02eee3045daee5168Mathieu Chartier      uintptr_t begin = reinterpret_cast<uintptr_t>(space->Begin());
1213720ef7680573c1afd12f99f02eee3045daee5168Mathieu Chartier      uintptr_t end = reinterpret_cast<uintptr_t>(space->End());
12141d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      scc.space = space->AsDlMallocSpace();
12151d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
12161d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      accounting::SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
1217fd678beb171a4686a4f2d53ca4188a4ade8fa54eMathieu Chartier      if (swap_bitmaps) {
1218fd678beb171a4686a4f2d53ca4188a4ade8fa54eMathieu Chartier        std::swap(live_bitmap, mark_bitmap);
1219fd678beb171a4686a4f2d53ca4188a4ade8fa54eMathieu Chartier      }
12201d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      if (!space->IsZygoteSpace()) {
12214654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum        base::TimingLogger::ScopedSplit split("SweepAllocSpace", &timings_);
1222cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier        // Bitmaps are pre-swapped for optimization which enables sweeping with the heap unlocked.
12231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        accounting::SpaceBitmap::SweepWalk(*live_bitmap, *mark_bitmap, begin, end,
12241d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                           &SweepCallback, reinterpret_cast<void*>(&scc));
1225cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier      } else {
12264654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum        base::TimingLogger::ScopedSplit split("SweepZygote", &timings_);
12271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        // Zygote sweep takes care of dirtying cards and clearing live bits, does not free actual
12281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        // memory.
12291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        accounting::SpaceBitmap::SweepWalk(*live_bitmap, *mark_bitmap, begin, end,
12301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                           &ZygoteSweepCallback, reinterpret_cast<void*>(&scc));
1231cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier      }
123258551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro    }
123358551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro  }
12342b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
12352b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  SweepLargeObjects(swap_bitmaps);
123658551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro}
123758551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro
1238e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartiervoid MarkSweep::SweepLargeObjects(bool swap_bitmaps) {
12394654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit("SweepLargeObjects", &timings_);
1240e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  // Sweep large objects
12411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
12421d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceSetMap* large_live_objects = large_object_space->GetLiveObjects();
12431d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  accounting::SpaceSetMap* large_mark_objects = large_object_space->GetMarkObjects();
1244e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  if (swap_bitmaps) {
1245e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    std::swap(large_live_objects, large_mark_objects);
1246e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  }
1247e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  // O(n*log(n)) but hopefully there are not too many large objects.
1248e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  size_t freed_objects = 0;
12492fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier  size_t freed_bytes = 0;
125050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
1251e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  for (const Object* obj : large_live_objects->GetObjects()) {
125202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    if (!large_mark_objects->Test(obj)) {
125302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      freed_bytes += large_object_space->Free(self, const_cast<Object*>(obj));
1254e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier      ++freed_objects;
1255e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    }
1256e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  }
1257e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_objects_.fetch_add(freed_objects);
1258e53225c7b8c98f8fc3855fc70f718e7f8abab307Mathieu Chartier  freed_large_object_bytes_.fetch_add(freed_bytes);
12592fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier  GetHeap()->RecordFree(freed_objects, freed_bytes);
1260e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier}
1261e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier
1262b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartiervoid MarkSweep::CheckReference(const Object* obj, const Object* ref, MemberOffset offset, bool is_static) {
126302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
12641d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (space->IsDlMallocSpace() && space->Contains(ref)) {
1265b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier      DCHECK(IsMarked(obj));
1266b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
1267b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier      bool is_marked = IsMarked(ref);
1268b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier      if (!is_marked) {
12691d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        LOG(INFO) << *space;
1270b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        LOG(WARNING) << (is_static ? "Static ref'" : "Instance ref'") << PrettyTypeOf(ref)
1271b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier                     << "' (" << reinterpret_cast<const void*>(ref) << ") in '" << PrettyTypeOf(obj)
1272b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier                     << "' (" << reinterpret_cast<const void*>(obj) << ") at offset "
1273b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier                     << reinterpret_cast<void*>(offset.Int32Value()) << " wasn't marked";
1274b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
1275b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
1276b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        DCHECK(klass != NULL);
1277ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom        const ObjectArray<ArtField>* fields = is_static ? klass->GetSFields() : klass->GetIFields();
1278b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        DCHECK(fields != NULL);
1279b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        bool found = false;
1280b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        for (int32_t i = 0; i < fields->GetLength(); ++i) {
1281ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom          const ArtField* cur = fields->Get(i);
1282b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier          if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
1283b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier            LOG(WARNING) << "Field referencing the alloc space was " << PrettyField(cur);
1284b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier            found = true;
1285b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier            break;
1286b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier          }
1287b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        }
1288b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        if (!found) {
1289b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier          LOG(WARNING) << "Could not find field in object alloc space with offset " << offset.Int32Value();
1290262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier        }
1291262e5ffa1d4b23f23af3dea762a71a0af4bfd4a9Mathieu Chartier
1292b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        bool obj_marked = heap_->GetCardTable()->IsDirty(obj);
1293b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        if (!obj_marked) {
1294b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier          LOG(WARNING) << "Object '" << PrettyTypeOf(obj) << "' "
1295b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier                       << "(" << reinterpret_cast<const void*>(obj) << ") contains references to "
1296b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier                       << "the alloc space, but wasn't card marked";
1297b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier        }
12985d76c435082332ef79a22962386fa92a0870e378Ian Rogers      }
12995d76c435082332ef79a22962386fa92a0870e378Ian Rogers    }
1300b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    break;
13015d76c435082332ef79a22962386fa92a0870e378Ian Rogers  }
13025d76c435082332ef79a22962386fa92a0870e378Ian Rogers}
13035d76c435082332ef79a22962386fa92a0870e378Ian Rogers
130469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Process the "referent" field in a java.lang.ref.Reference.  If the
130569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// referent has not yet been marked, put it on the appropriate list in
130694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier// the heap for later processing.
130794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiervoid MarkSweep::DelayReferenceReferent(mirror::Class* klass, Object* obj) {
130894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  DCHECK(klass != nullptr);
13090cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  DCHECK(klass->IsReferenceClass());
131094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  DCHECK(obj != NULL);
1311b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  Object* referent = heap_->GetReferenceReferent(obj);
131294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  if (referent != NULL && !IsMarked(referent)) {
131394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (kCountJavaLangRefs) {
131494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      ++reference_count_;
131594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    }
131694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    Thread* self = Thread::Current();
131794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // TODO: Remove these locks, and use atomic stacks for storing references?
1318b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier    // We need to check that the references haven't already been enqueued since we can end up
1319b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier    // scanning the same reference multiple times due to dirty cards.
13200cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    if (klass->IsSoftReferenceClass()) {
132194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      MutexLock mu(self, *heap_->GetSoftRefQueueLock());
1322b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      if (!heap_->IsEnqueued(obj)) {
1323b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier        heap_->EnqueuePendingReference(obj, &soft_reference_list_);
1324b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      }
13250cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    } else if (klass->IsWeakReferenceClass()) {
132694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      MutexLock mu(self, *heap_->GetWeakRefQueueLock());
1327b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      if (!heap_->IsEnqueued(obj)) {
1328b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier        heap_->EnqueuePendingReference(obj, &weak_reference_list_);
1329b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      }
13300cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    } else if (klass->IsFinalizerReferenceClass()) {
133194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      MutexLock mu(self, *heap_->GetFinalizerRefQueueLock());
1332b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      if (!heap_->IsEnqueued(obj)) {
1333b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier        heap_->EnqueuePendingReference(obj, &finalizer_reference_list_);
1334b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      }
13350cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    } else if (klass->IsPhantomReferenceClass()) {
133694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      MutexLock mu(self, *heap_->GetPhantomRefQueueLock());
1337b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      if (!heap_->IsEnqueued(obj)) {
1338b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier        heap_->EnqueuePendingReference(obj, &phantom_reference_list_);
1339b4ea4de2d6b63a3855968f2748878018a27af106Mathieu Chartier      }
134094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    } else {
134194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      LOG(FATAL) << "Invalid reference type " << PrettyClass(klass)
134294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                 << " " << std::hex << klass->GetAccessFlags();
134369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
134469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
134569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
134669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
1347357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartiervoid MarkSweep::ScanRoot(const Object* obj) {
1348357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  ScanObject(obj);
1349357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier}
1350357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
135102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass MarkObjectVisitor {
135202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier public:
135394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  explicit MarkObjectVisitor(MarkSweep* const mark_sweep) ALWAYS_INLINE : mark_sweep_(mark_sweep) {}
135402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
13552b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // TODO: Fixme when anotatalysis works with visitors.
1356df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  void operator()(const Object* /* obj */, const Object* ref, const MemberOffset& /* offset */,
135794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                  bool /* is_static */) const ALWAYS_INLINE
13582b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      NO_THREAD_SAFETY_ANALYSIS {
135994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    if (kCheckLocks) {
13602b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
13612b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier      Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
13622b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier    }
136302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    mark_sweep_->MarkObject(ref);
136402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
136502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
136602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier private:
136702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  MarkSweep* const mark_sweep_;
136802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier};
136902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
137069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Scans an object reference.  Determines the type of the reference
137169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// and dispatches to a specialized scanning routine.
1372cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartiervoid MarkSweep::ScanObject(const Object* obj) {
137302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  MarkObjectVisitor visitor(this);
137402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  ScanObjectVisit(obj, visitor);
137502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}
137602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
13772775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartiervoid MarkSweep::ProcessMarkStackParallel(size_t thread_count) {
137802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  Thread* self = Thread::Current();
137902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  ThreadPool* thread_pool = GetHeap()->GetThreadPool();
13802775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  const size_t chunk_size = std::min(mark_stack_->Size() / thread_count + 1,
13812775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier                                     static_cast<size_t>(MarkStackTask<false>::kMaxSize));
138294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  CHECK_GT(chunk_size, 0U);
138394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Split the current mark stack up into work tasks.
138494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  for (mirror::Object **it = mark_stack_->Begin(), **end = mark_stack_->End(); it < end; ) {
138594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    const size_t delta = std::min(static_cast<size_t>(end - it), chunk_size);
138694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    thread_pool->AddTask(self, new MarkStackTask<false>(thread_pool, this, delta,
138794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier                                                        const_cast<const mirror::Object**>(it)));
138894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    it += delta;
138902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
13902775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  thread_pool->SetMaxActiveWorkers(thread_count - 1);
139102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  thread_pool->StartWorkers(self);
13922775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  thread_pool->Wait(self, true, true);
139394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  thread_pool->StopWorkers(self);
139402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  mark_stack_->Reset();
139502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  CHECK_EQ(work_chunks_created_, work_chunks_deleted_) << " some of the work chunks were leaked";
139669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
139769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
13985d76c435082332ef79a22962386fa92a0870e378Ian Rogers// Scan anything that's on the mark stack.
139994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartiervoid MarkSweep::ProcessMarkStack(bool paused) {
14004446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("ProcessMarkStack");
14012775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  size_t thread_count = GetThreadCount(paused);
14022775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  if (kParallelProcessMarkStack && thread_count > 1 &&
14032775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier      mark_stack_->Size() >= kMinimumParallelMarkStackSize) {
14042775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier    ProcessMarkStackParallel(thread_count);
140594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  } else {
140694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    // TODO: Tune this.
140794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    static const size_t kFifoSize = 4;
140894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    BoundedFifoPowerOfTwo<const Object*, kFifoSize> prefetch_fifo;
1409d8195f19840911a73b1491dfc8e7c18139753731Mathieu Chartier    for (;;) {
141094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      const Object* obj = NULL;
141194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      if (kUseMarkStackPrefetch) {
141294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        while (!mark_stack_->IsEmpty() && prefetch_fifo.size() < kFifoSize) {
141394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          const Object* obj = mark_stack_->PopBack();
141494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          DCHECK(obj != NULL);
141594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          __builtin_prefetch(obj);
141694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          prefetch_fifo.push_back(obj);
141794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
141894c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (prefetch_fifo.empty()) {
141994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
142094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
142194c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        obj = prefetch_fifo.front();
142294c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        prefetch_fifo.pop_front();
142394c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier      } else {
142494c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        if (mark_stack_->IsEmpty()) {
142594c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier          break;
142694c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        }
142794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier        obj = mark_stack_->PopBack();
1428d8195f19840911a73b1491dfc8e7c18139753731Mathieu Chartier      }
1429d8195f19840911a73b1491dfc8e7c18139753731Mathieu Chartier      DCHECK(obj != NULL);
1430d8195f19840911a73b1491dfc8e7c18139753731Mathieu Chartier      ScanObject(obj);
1431357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
1432357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
14334446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
143469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
143569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
143669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Walks the reference list marking any references subject to the
143769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// reference clearing policy.  References with a black referent are
143869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// removed from the list.  References with white referents biased
143969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// toward saving are blackened and also removed from the list.
144069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapirovoid MarkSweep::PreserveSomeSoftReferences(Object** list) {
144169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(list != NULL);
144269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Object* clear = NULL;
144369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  size_t counter = 0;
1444b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier
1445b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier  DCHECK(mark_stack_->IsEmpty());
1446b43b7d42b0c497333564e76be953157066c2b995Mathieu Chartier
14474446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("PreserveSomeSoftReferences");
144869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  while (*list != NULL) {
1449b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* ref = heap_->DequeuePendingReference(list);
1450b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* referent = heap_->GetReferenceReferent(ref);
145169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    if (referent == NULL) {
145269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      // Referent was cleared by the user during marking.
145369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      continue;
145469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
145569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    bool is_marked = IsMarked(referent);
145669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    if (!is_marked && ((++counter) & 1)) {
145769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      // Referent is white and biased toward saving, mark it.
145869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      MarkObject(referent);
145969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      is_marked = true;
146069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
146169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    if (!is_marked) {
146269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      // Referent is white, queue it for clearing.
1463b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_->EnqueuePendingReference(ref, &clear);
146469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
146569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
146669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  *list = clear;
14674446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
14684446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum
146994c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  // Restart the mark with the newly black references added to the root set.
147094c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier  ProcessMarkStack(true);
147169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
147269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
14737469ebf3888b8037421cb6834f37f946646265ecMathieu Chartierinline bool MarkSweep::IsMarked(const Object* object) const
14747469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier    SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
14759642c96bd5a1ccc4e221de9c0af4a545af8182d2Mathieu Chartier  if (IsImmune(object)) {
14767469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier    return true;
14777469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  }
14787469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  DCHECK(current_mark_bitmap_ != NULL);
14797469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  if (current_mark_bitmap_->HasAddress(object)) {
14807469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier    return current_mark_bitmap_->Test(object);
14817469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  }
14827469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  return heap_->GetMarkBitmap()->Test(object);
14837469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
14847469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
148569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Unlink the reference list clearing references objects with white
148669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// referents.  Cleared references registered to a reference queue are
148769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// scheduled for appending by the heap worker thread.
148869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapirovoid MarkSweep::ClearWhiteReferences(Object** list) {
148969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(list != NULL);
149069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  while (*list != NULL) {
1491b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* ref = heap_->DequeuePendingReference(list);
1492b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* referent = heap_->GetReferenceReferent(ref);
149369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    if (referent != NULL && !IsMarked(referent)) {
149469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      // Referent is white, clear it.
1495b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_->ClearReferenceReferent(ref);
1496b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      if (heap_->IsEnqueuable(ref)) {
1497b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes        heap_->EnqueueReference(ref, &cleared_reference_list_);
149869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      }
149969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
150069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
150169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*list == NULL);
150269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
150369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
150469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// Enqueues finalizer references with white referents.  White
150569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// referents are blackened, moved to the zombie field, and the
150669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro// referent field is cleared.
150769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapirovoid MarkSweep::EnqueueFinalizerReferences(Object** list) {
150869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(list != NULL);
15094446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("EnqueueFinalizerReferences");
1510b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  MemberOffset zombie_offset = heap_->GetFinalizerReferenceZombieOffset();
151169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  bool has_enqueued = false;
151269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  while (*list != NULL) {
1513b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* ref = heap_->DequeuePendingReference(list);
1514b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Object* referent = heap_->GetReferenceReferent(ref);
151569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    if (referent != NULL && !IsMarked(referent)) {
151669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      MarkObject(referent);
151769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      // If the referent is non-null the reference must queuable.
1518b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      DCHECK(heap_->IsEnqueuable(ref));
15190cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers      ref->SetFieldObject(zombie_offset, referent, false);
1520b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_->ClearReferenceReferent(ref);
1521b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      heap_->EnqueueReference(ref, &cleared_reference_list_);
152269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro      has_enqueued = true;
152369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    }
152469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
15254446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
152669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  if (has_enqueued) {
152794c32c5f01c7d44781317bf23933ed0a5bc4b796Mathieu Chartier    ProcessMarkStack(true);
152869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
152969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*list == NULL);
153069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
153169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
153258551df3c2646ed507feec9e9eb3768085a76059Carl Shapiro// Process reference class instances and schedule finalizations.
153369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapirovoid MarkSweep::ProcessReferences(Object** soft_references, bool clear_soft,
153469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro                                  Object** weak_references,
153569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro                                  Object** finalizer_references,
153669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro                                  Object** phantom_references) {
153769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(soft_references != NULL);
153869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(weak_references != NULL);
153969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(finalizer_references != NULL);
154069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(phantom_references != NULL);
154169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
154269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Unless we are in the zygote or required to clear soft references
154369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // with white references, preserve some white referents.
15442945e2455ba87e15b65f4a6a737bcdc8c0f2f31bIan Rogers  if (!clear_soft && !Runtime::Current()->IsZygote()) {
154569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    PreserveSomeSoftReferences(soft_references);
154669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
154769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
15484446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("ProcessReferences");
154969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Clear all remaining soft and weak references with white
155069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // referents.
155169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  ClearWhiteReferences(soft_references);
155269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  ClearWhiteReferences(weak_references);
15534446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
155469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
155569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Preserve all white objects with finalize methods and schedule
155669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // them for finalization.
155769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  EnqueueFinalizerReferences(finalizer_references);
155869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
15594446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.StartSplit("ProcessReferences");
156069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Clear all f-reachable soft and weak references with white
156169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // referents.
156269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  ClearWhiteReferences(soft_references);
156369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  ClearWhiteReferences(weak_references);
156469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
156569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Clear all phantom references with white referents.
156669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  ClearWhiteReferences(phantom_references);
156769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
156869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // At this point all reference lists should be empty.
156969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*soft_references == NULL);
157069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*weak_references == NULL);
157169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*finalizer_references == NULL);
157269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  DCHECK(*phantom_references == NULL);
15734446ab9e70dde779d97f451c4904f6b8770232bdAnwar Ghuloum  timings_.EndSplit();
157469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
157569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
15767469ebf3888b8037421cb6834f37f946646265ecMathieu Chartiervoid MarkSweep::UnBindBitmaps() {
15774654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("UnBindBitmaps", &timings_);
157802e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
15791d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (space->IsDlMallocSpace()) {
15801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      space::DlMallocSpace* alloc_space = space->AsDlMallocSpace();
15817469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      if (alloc_space->temp_bitmap_.get() != NULL) {
15827469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        // At this point, the temp_bitmap holds our old mark bitmap.
15831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        accounting::SpaceBitmap* new_bitmap = alloc_space->temp_bitmap_.release();
15847469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        GetHeap()->GetMarkBitmap()->ReplaceBitmap(alloc_space->mark_bitmap_.get(), new_bitmap);
15857469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        CHECK_EQ(alloc_space->mark_bitmap_.release(), alloc_space->live_bitmap_.get());
15867469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        alloc_space->mark_bitmap_.reset(new_bitmap);
15877469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier        DCHECK(alloc_space->temp_bitmap_.get() == NULL);
15887469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      }
15897469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier    }
15907469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier  }
15917469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier}
15927469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier
15932b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartiervoid MarkSweep::FinishPhase() {
15944654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  base::TimingLogger::ScopedSplit split("FinishPhase", &timings_);
15954654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  // Can't enqueue references if we hold the mutator lock.
15962b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  Object* cleared_references = GetClearedReferences();
15971d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Heap* heap = GetHeap();
15984654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("EnqueueClearedReferences");
15991d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  heap->EnqueueClearedReferences(&cleared_references);
16002b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
16014654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("PostGcVerification");
16021d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  heap->PostGcVerification(this);
16032b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
16044654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("GrowForUtilization");
1605bdd0fb9bf5e3af9d2f0366652979ac04b05d3d1eMathieu Chartier  heap->GrowForUtilization(GetGcType(), GetDurationNs());
160665db880c73718f89278dac8975d58d3a49ff1fdbMathieu Chartier
16074654322261c8e4d799acdea60a7e227f33c5c2dbAnwar Ghuloum  timings_.NewSplit("RequestHeapTrim");
16081d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  heap->RequestHeapTrim();
160965db880c73718f89278dac8975d58d3a49ff1fdbMathieu Chartier
16102b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Update the cumulative statistics
16111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  total_time_ns_ += GetDurationNs();
16121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  total_paused_time_ns_ += std::accumulate(GetPauseTimes().begin(), GetPauseTimes().end(), 0,
16131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                           std::plus<uint64_t>());
16142775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  total_freed_objects_ += GetFreedObjects() + GetFreedLargeObjects();
16152775ee4f82dff260663ca16adddc0b15327aaa42Mathieu Chartier  total_freed_bytes_ += GetFreedBytes() + GetFreedLargeObjectBytes();
16162b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
16172b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Ensure that the mark stack is empty.
16182b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  CHECK(mark_stack_->IsEmpty());
16192b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier
1620d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier  if (kCountScannedTypes) {
1621d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "MarkSweep scanned classes=" << class_count_ << " arrays=" << array_count_
1622d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier             << " other=" << other_count_;
162302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
162402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
162502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (kCountTasks) {
1626d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "Total number of work chunks allocated: " << work_chunks_created_;
162702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
162802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
162902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (kMeasureOverhead) {
1630d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "Overhead time " << PrettyDuration(overhead_time_);
163102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
163202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
163302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (kProfileLargeObjects) {
1634d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "Large objects tested " << large_object_test_ << " marked " << large_object_mark_;
163502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
163602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
163702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  if (kCountClassesMarked) {
1638d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "Classes marked " << classes_marked_;
1639d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier  }
1640d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier
1641d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier  if (kCountJavaLangRefs) {
1642d22d54849c96760aa1efa259d6dcfbace54da2afMathieu Chartier    VLOG(gc) << "References scanned " << reference_count_;
164302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  }
164402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier
16452b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  // Update the cumulative loggers.
16462b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  cumulative_timings_.Start();
16476f28d91aab952e3244fbb4e707fa38f85538f374Anwar Ghuloum  cumulative_timings_.AddLogger(timings_);
16482b82db45c09450022199376c3a5420eacf2aa81eMathieu Chartier  cumulative_timings_.End();
1649357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier
165002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier  // Clear all of the spaces' mark bitmaps.
165102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
16521d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    if (space->GetGcRetentionPolicy() != space::kGcRetentionPolicyNeverCollect) {
16537469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier      space->GetMarkBitmap()->Clear();
1654b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
1655b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier  }
16565301cd241b4d8afbfc1211e107c41f1b15c6bd48Mathieu Chartier  mark_stack_->Reset();
1657e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier
1658e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  // Reset the marked large objects.
16591d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  space::LargeObjectSpace* large_objects = GetHeap()->GetLargeObjectsSpace();
1660e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier  large_objects->GetMarkObjects()->Clear();
166169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}
166269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
16631d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace collector
16641d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace gc
166569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro}  // namespace art
1666