/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_
#define ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_

#include "heap.h"

#include "base/mutex-inl.h"
#include "gc/accounting/heap_bitmap-inl.h"
#include "gc/space/bump_pointer_space-walk-inl.h"
#include "gc/space/region_space-inl.h"
#include "mirror/object-inl.h"
#include "obj_ptr-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"

namespace art {
namespace gc {

// Visit objects when threads aren't suspended. If concurrent moving
// GC, disable moving GC and suspend threads and then visit objects.
template <typename Visitor>
inline void Heap::VisitObjects(Visitor&& visitor) {
  Thread* self = Thread::Current();
  Locks::mutator_lock_->AssertSharedHeld(self);
  DCHECK(!Locks::mutator_lock_->IsExclusiveHeld(self)) << "Call VisitObjectsPaused() instead";
  if (IsGcConcurrentAndMoving()) {
    // Concurrent moving GC. Just suspending threads isn't sufficient
    // because a collection isn't one big pause and we could suspend
    // threads in the middle (between phases) of a concurrent moving
    // collection where it's not easily known which objects are alive
    // (both the region space and the non-moving space) or which
    // copies of objects to visit, and the to-space invariant could be
    // easily broken. Visit objects while GC isn't running by using
    // IncrementDisableMovingGC() and threads are suspended.
    IncrementDisableMovingGC(self);
    {
      ScopedThreadSuspension sts(self, ThreadState::kWaitingForVisitObjects);
      ScopedSuspendAll ssa(__FUNCTION__);
      VisitObjectsInternalRegionSpace(visitor);
      VisitObjectsInternal(visitor);
    }
    DecrementDisableMovingGC(self);
  } else {
    // Since concurrent moving GC has thread suspension, also poison ObjPtr the normal case to
    // catch bugs.
    self->PoisonObjectPointers();
    // GCs can move objects, so don't allow this.
    ScopedAssertNoThreadSuspension ants("Visiting objects");
    DCHECK(region_space_ == nullptr);
    VisitObjectsInternal(visitor);
    self->PoisonObjectPointers();
  }
}

template <typename Visitor>
inline void Heap::VisitObjectsPaused(Visitor&& visitor) {
  Thread* self = Thread::Current();
  Locks::mutator_lock_->AssertExclusiveHeld(self);
  VisitObjectsInternalRegionSpace(visitor);
  VisitObjectsInternal(visitor);
}

// Visit objects in the region spaces.
template <typename Visitor>
inline void Heap::VisitObjectsInternalRegionSpace(Visitor&& visitor) {
  Thread* self = Thread::Current();
  Locks::mutator_lock_->AssertExclusiveHeld(self);
  if (region_space_ != nullptr) {
    DCHECK(IsGcConcurrentAndMoving());
    if (!zygote_creation_lock_.IsExclusiveHeld(self)) {
      // Exclude the pre-zygote fork time where the semi-space collector
      // calls VerifyHeapReferences() as part of the zygote compaction
      // which then would call here without the moving GC disabled,
      // which is fine.
      bool is_thread_running_gc = false;
      if (kIsDebugBuild) {
        MutexLock mu(self, *gc_complete_lock_);
        is_thread_running_gc = self == thread_running_gc_;
      }
      // If we are not the thread running the GC on in a GC exclusive region, then moving GC
      // must be disabled.
      DCHECK(is_thread_running_gc || IsMovingGCDisabled(self));
    }
    region_space_->Walk(visitor);
  }
}

// Visit objects in the other spaces.
template <typename Visitor>
inline void Heap::VisitObjectsInternal(Visitor&& visitor) {
  if (bump_pointer_space_ != nullptr) {
    // Visit objects in bump pointer space.
    bump_pointer_space_->Walk(visitor);
  }
  // TODO: Switch to standard begin and end to use ranged a based loop.
  for (auto* it = allocation_stack_->Begin(), *end = allocation_stack_->End(); it < end; ++it) {
    mirror::Object* const obj = it->AsMirrorPtr();

    mirror::Class* kls = nullptr;
    if (obj != nullptr && (kls = obj->GetClass()) != nullptr) {
      // Below invariant is safe regardless of what space the Object is in.
      // For speed reasons, only perform it when Rosalloc could possibly be used.
      // (Disabled for read barriers because it never uses Rosalloc).
      // (See the DCHECK in RosAllocSpace constructor).
      if (!gUseReadBarrier) {
        // Rosalloc has a race in allocation. Objects can be written into the allocation
        // stack before their header writes are visible to this thread.
        // See b/28790624 for more details.
        //
        // obj.class will either be pointing to a valid Class*, or it will point
        // to a rosalloc free buffer.
        //
        // If it's pointing to a valid Class* then that Class's Class will be the
        // ClassClass (whose Class is itself).
        //
        // A rosalloc free buffer will point to another rosalloc free buffer
        // (or to null), and never to itself.
        //
        // Either way dereferencing while its not-null is safe because it will
        // always point to another valid pointer or to null.
        mirror::Class* klsClass = kls->GetClass();

        if (klsClass == nullptr) {
          continue;
        } else if (klsClass->GetClass() != klsClass) {
          continue;
        }
      } else {
        // Ensure the invariant is not broken for non-rosalloc cases.
        DCHECK(Heap::rosalloc_space_ == nullptr)
            << "unexpected rosalloc with read barriers";
        DCHECK(kls->GetClass() != nullptr)
            << "invalid object: class does not have a class";
        DCHECK_EQ(kls->GetClass()->GetClass(), kls->GetClass())
            << "invalid object: class's class is not ClassClass";
      }

      // Avoid the race condition caused by the object not yet being written into the allocation
      // stack or the class not yet being written in the object. Or, if
      // kUseThreadLocalAllocationStack, there can be nulls on the allocation stack.
      visitor(obj);
    }
  }
  {
    ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
    GetLiveBitmap()->Visit<Visitor>(visitor);
  }
}

}  // namespace gc
}  // namespace art

#endif  // ART_RUNTIME_GC_HEAP_VISIT_OBJECTS_INL_H_
