/*
 * Copyright (C) 2015 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_LINEAR_ALLOC_H_
#define ART_RUNTIME_LINEAR_ALLOC_H_

#include "base/arena_allocator.h"
#include "base/casts.h"
#include "base/mutex.h"

namespace art {

class ArenaPool;

enum class LinearAllocKind : uint32_t {
  kNoGCRoots = 0,  // No GC-root kind should always be 0.
  kGCRootArray,
  kArtMethodArray,
  kArtFieldArray,
  kDexCacheArray,
  kArtMethod
};

// Header for every allocation in LinearAlloc. The header provides the type
// and size information to the GC for invoking the right visitor.
class TrackingHeader final {
 public:
  static constexpr uint32_t kIs16Aligned = 1;
  TrackingHeader(size_t size, LinearAllocKind kind, bool is_16_aligned = false)
      : kind_(kind), size_(dchecked_integral_cast<uint32_t>(size)) {
    // We need the last bit to store 16-byte alignment flag.
    CHECK_EQ(size_ & kIs16Aligned, 0u);
    if (is_16_aligned) {
      size_ |= kIs16Aligned;
    }
  }

  LinearAllocKind GetKind() const { return kind_; }
  // Since we are linearly allocating and hop from one object to the next during
  // visits, reading 'size_ == 0' indicates that there are no more objects to
  // visit in the given page. But ASAN detects it as use-after-poison access.
  ATTRIBUTE_NO_SANITIZE_ADDRESS size_t GetSize() const { return size_ & ~kIs16Aligned; }
  bool Is16Aligned() const { return size_ & kIs16Aligned; }

 private:
  LinearAllocKind kind_;
  uint32_t size_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(TrackingHeader);
};

std::ostream& operator<<(std::ostream& os, LinearAllocKind value);

// TODO: Support freeing if we add class unloading.
class LinearAlloc {
 public:
  static constexpr size_t kAlignment = 8u;
  static_assert(kAlignment >= ArenaAllocator::kAlignment);
  static_assert(sizeof(TrackingHeader) == ArenaAllocator::kAlignment);

  explicit LinearAlloc(ArenaPool* pool, bool track_allocs)
      : lock_("linear alloc"), allocator_(pool), track_allocations_(track_allocs) {}

  void* Alloc(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_);
  void* AllocAlign16(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_);

  // Realloc never frees the input pointer, it is the caller's job to do this if necessary.
  void* Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size, LinearAllocKind kind)
      REQUIRES(!lock_);

  // Allocate an array of structs of type T.
  template<class T>
  T* AllocArray(Thread* self, size_t elements, LinearAllocKind kind) REQUIRES(!lock_) {
    return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T), kind));
  }

  // Return the number of bytes used in the allocator.
  size_t GetUsedMemory() const REQUIRES(!lock_);

  ArenaPool* GetArenaPool() REQUIRES(!lock_);
  // Force arena allocator to ask for a new arena on next allocation. This
  // is to preserve private/shared clean pages across zygote fork.
  void SetupForPostZygoteFork(Thread* self) REQUIRES(!lock_);

  // Return true if the linear alloc contains an address.
  bool Contains(void* ptr) const REQUIRES(!lock_);

  // Unsafe version of 'Contains' only to be used when the allocator is going
  // to be deleted.
  bool ContainsUnsafe(void* ptr) const NO_THREAD_SAFETY_ANALYSIS {
    return allocator_.Contains(ptr);
  }

  // Set the given object as the first object for all the pages where the
  // page-beginning overlaps with the object.
  void SetFirstObject(void* begin, size_t bytes) const REQUIRES(lock_);

 private:
  mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  ArenaAllocator allocator_ GUARDED_BY(lock_);
  const bool track_allocations_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(LinearAlloc);
};

}  // namespace art

#endif  // ART_RUNTIME_LINEAR_ALLOC_H_
