/*
 * Copyright (C) 2011 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_MIRROR_CLASS_ALLOC_INL_H_
#define ART_RUNTIME_MIRROR_CLASS_ALLOC_INL_H_

#include "class-inl.h"

#include "gc/allocator_type.h"
#include "gc/heap-inl.h"
#include "object-inl.h"
#include "runtime.h"

namespace art {
namespace mirror {

inline void Class::CheckObjectAlloc() {
  DCHECK(!IsArrayClass())
      << PrettyClass()
      << "A array shouldn't be allocated through this "
      << "as it requires a pre-fence visitor that sets the class size.";
  DCHECK(!IsClassClass())
      << PrettyClass()
      << "A class object shouldn't be allocated through this "
      << "as it requires a pre-fence visitor that sets the class size.";
  DCHECK(!IsStringClass())
      << PrettyClass()
      << "A string shouldn't be allocated through this "
      << "as it requires a pre-fence visitor that sets the class size.";
  DCHECK(IsInstantiable()) << PrettyClass();
  // TODO: decide whether we want this check. It currently fails during bootstrap.
  // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass();
  DCHECK_GE(this->object_size_, sizeof(Object));
}

template<bool kIsInstrumented, Class::AddFinalizer kAddFinalizer, bool kCheckAddFinalizer>
inline ObjPtr<Object> Class::Alloc(Thread* self, gc::AllocatorType allocator_type) {
  CheckObjectAlloc();
  gc::Heap* heap = Runtime::Current()->GetHeap();
  bool add_finalizer;
  switch (kAddFinalizer) {
    case Class::AddFinalizer::kUseClassTag:
      add_finalizer = IsFinalizable();
      break;
    case Class::AddFinalizer::kNoAddFinalizer:
      add_finalizer = false;
      DCHECK_IMPLIES(kCheckAddFinalizer, !IsFinalizable());
      break;
  }
  // Note that the `this` pointer may be invalidated after the allocation.
  ObjPtr<Object> obj =
      heap->AllocObjectWithAllocator<kIsInstrumented, /*kCheckLargeObject=*/ false>(
          self, this, this->object_size_, allocator_type, VoidFunctor());
  if (add_finalizer && LIKELY(obj != nullptr)) {
    heap->AddFinalizerReference(self, &obj);
    if (UNLIKELY(self->IsExceptionPending())) {
      // Failed to allocate finalizer reference, it means that the whole allocation failed.
      obj = nullptr;
    }
  }
  return obj;
}

inline ObjPtr<Object> Class::AllocObject(Thread* self) {
  return Alloc(self, Runtime::Current()->GetHeap()->GetCurrentAllocator());
}

inline ObjPtr<Object> Class::AllocNonMovableObject(Thread* self) {
  return Alloc(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator());
}

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_CLASS_ALLOC_INL_H_
