/*
 * Copyright (C) 2025 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.
 */

#include "src/protovm/allocator.h"

namespace perfetto {
namespace protovm {

Allocator::Allocator(size_t memory_limit_bytes)
    : memory_limit_bytes_{memory_limit_bytes}, used_memory_bytes_{0} {}

StatusOr<OwnedPtr<MapNode>> Allocator::CreateMapNode(uint64_t key,
                                                     OwnedPtr<Node> value) {
  PERFETTO_DCHECK(value);
  auto p = Allocate();
  if (!p.IsOk()) {
    Delete(value.release());
    PROTOVM_RETURN(p);
  }
  new (*p) MapNode{key, std::move(value)};
  return OwnedPtr<MapNode>(static_cast<MapNode*>(*p));
}

StatusOr<Node::Bytes> Allocator::AllocateAndCopyBytes(
    protozero::ConstBytes data) {
  if (used_memory_bytes_ + data.size > memory_limit_bytes_) {
    PROTOVM_ABORT(
        "Failed to allocate %zu bytes. Memory limit: %zu bytes. Used: %zu "
        "bytes.)",
        data.size, memory_limit_bytes_, used_memory_bytes_);
  }

  if (data.size == 0) {
    return Node::Bytes{nullptr, 0};
  }

  auto copy = OwnedPtr<void>{malloc(data.size)};
  if (!copy) {
    PROTOVM_ABORT("Failed to malloc %zu bytes", data.size);
  }
  used_memory_bytes_ += data.size;
  memcpy(copy.get(), data.data, data.size);

  return Node::Bytes{std::move(copy), data.size};
}

void Allocator::Delete(Node* node) {
  DeleteReferencedData(node);
  node->~Node();
  slab_allocator_.Free(node);
  used_memory_bytes_ -= kNodeSize;
}

void Allocator::Delete(MapNode* node) {
  Delete(node->value.release());
  node->~MapNode();
  slab_allocator_.Free(node);
  used_memory_bytes_ -= kNodeSize;
}

void Allocator::DeleteReferencedData(Node* node) {
  if (auto* message = node->GetIf<Node::Message>()) {
    DeleteReferencedData(message);
  } else if (auto* indexed_fields = node->GetIf<Node::IndexedRepeatedField>()) {
    for (auto it = indexed_fields->index_to_node.begin(); it;) {
      auto& map_node = *it;
      it = indexed_fields->index_to_node.Remove(it);
      Delete(&map_node);
    }
  } else if (auto* mapped_fields = node->GetIf<Node::MappedRepeatedField>()) {
    for (auto it = mapped_fields->key_to_node.begin(); it;) {
      auto& map_node = *it;
      it = mapped_fields->key_to_node.Remove(it);
      Delete(&map_node);
    }
  } else if (auto* bytes = node->GetIf<Node::Bytes>()) {
    DeleteReferencedData(bytes);
  }
}

void Allocator::DeleteReferencedData(Node::Message* message) {
  for (auto it = message->field_id_to_node.begin(); it;) {
    auto& map_node = *it;
    it = message->field_id_to_node.Remove(it);
    Delete(&map_node);
  }
}

void Allocator::DeleteReferencedData(Node::Bytes* bytes) {
  DeallocateBytes(std::move(bytes->data), bytes->size);
}

void Allocator::DeallocateBytes(OwnedPtr<void> p, size_t size) {
  free(p.release());
  used_memory_bytes_ -= size;
}

StatusOr<void*> Allocator::Allocate() {
  if (used_memory_bytes_ + kNodeSize > memory_limit_bytes_) {
    PROTOVM_ABORT(
        "Failed to allocate element (%zu bytes). Memory limit: %zu [bytes]. "
        "Used: %zu "
        "[bytes].)",
        kNodeSize, memory_limit_bytes_, used_memory_bytes_);
  }
  auto* p = slab_allocator_.Allocate();
  if (!p) {
    PROTOVM_ABORT("Failed to allocate node");
  }
  used_memory_bytes_ += kNodeSize;
  return p;
}

}  // namespace protovm
}  // namespace perfetto
