// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The common functionality when building with or without snapshots.

#include "src/snapshot/snapshot.h"

#include "src/api.h"
#include "src/base/platform/platform.h"
#include "src/full-codegen/full-codegen.h"
#include "src/snapshot/deserializer.h"
#include "src/snapshot/snapshot-source-sink.h"
#include "src/version.h"

namespace v8 {
namespace internal {

#ifdef DEBUG
bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
  return !Snapshot::ExtractStartupData(snapshot_blob).is_empty() &&
         !Snapshot::ExtractContextData(snapshot_blob).is_empty();
}
#endif  // DEBUG


bool Snapshot::HaveASnapshotToStartFrom(Isolate* isolate) {
  // Do not use snapshots if the isolate is used to create snapshots.
  return isolate->snapshot_blob() != NULL &&
         isolate->snapshot_blob()->data != NULL;
}


bool Snapshot::EmbedsScript(Isolate* isolate) {
  if (!isolate->snapshot_available()) return false;
  return ExtractMetadata(isolate->snapshot_blob()).embeds_script();
}


uint32_t Snapshot::SizeOfFirstPage(Isolate* isolate, AllocationSpace space) {
  DCHECK(space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE);
  if (!isolate->snapshot_available()) {
    return static_cast<uint32_t>(MemoryAllocator::PageAreaSize(space));
  }
  uint32_t size;
  int offset = kFirstPageSizesOffset + (space - FIRST_PAGED_SPACE) * kInt32Size;
  memcpy(&size, isolate->snapshot_blob()->data + offset, kInt32Size);
  return size;
}


bool Snapshot::Initialize(Isolate* isolate) {
  if (!isolate->snapshot_available()) return false;
  base::ElapsedTimer timer;
  if (FLAG_profile_deserialization) timer.Start();

  const v8::StartupData* blob = isolate->snapshot_blob();
  Vector<const byte> startup_data = ExtractStartupData(blob);
  SnapshotData snapshot_data(startup_data);
  Deserializer deserializer(&snapshot_data);
  bool success = isolate->Init(&deserializer);
  if (FLAG_profile_deserialization) {
    double ms = timer.Elapsed().InMillisecondsF();
    int bytes = startup_data.length();
    PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
  }
  return success;
}


MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
    Isolate* isolate, Handle<JSGlobalProxy> global_proxy) {
  if (!isolate->snapshot_available()) return Handle<Context>();
  base::ElapsedTimer timer;
  if (FLAG_profile_deserialization) timer.Start();

  const v8::StartupData* blob = isolate->snapshot_blob();
  Vector<const byte> context_data = ExtractContextData(blob);
  SnapshotData snapshot_data(context_data);
  Deserializer deserializer(&snapshot_data);

  MaybeHandle<Object> maybe_context =
      deserializer.DeserializePartial(isolate, global_proxy);
  Handle<Object> result;
  if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
  CHECK(result->IsContext());
  if (FLAG_profile_deserialization) {
    double ms = timer.Elapsed().InMillisecondsF();
    int bytes = context_data.length();
    PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms);
  }
  return Handle<Context>::cast(result);
}


void CalculateFirstPageSizes(bool is_default_snapshot,
                             const SnapshotData& startup_snapshot,
                             const SnapshotData& context_snapshot,
                             uint32_t* sizes_out) {
  Vector<const SerializedData::Reservation> startup_reservations =
      startup_snapshot.Reservations();
  Vector<const SerializedData::Reservation> context_reservations =
      context_snapshot.Reservations();
  int startup_index = 0;
  int context_index = 0;

  if (FLAG_profile_deserialization) {
    int startup_total = 0;
    int context_total = 0;
    for (auto& reservation : startup_reservations) {
      startup_total += reservation.chunk_size();
    }
    for (auto& reservation : context_reservations) {
      context_total += reservation.chunk_size();
    }
    PrintF(
        "Deserialization will reserve:\n"
        "%10d bytes per isolate\n"
        "%10d bytes per context\n",
        startup_total, context_total);
  }

  for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
    bool single_chunk = true;
    while (!startup_reservations[startup_index].is_last()) {
      single_chunk = false;
      startup_index++;
    }
    while (!context_reservations[context_index].is_last()) {
      single_chunk = false;
      context_index++;
    }

    uint32_t required = kMaxUInt32;
    if (single_chunk) {
      // If both the startup snapshot data and the context snapshot data on
      // this space fit in a single page, then we consider limiting the size
      // of the first page. For this, we add the chunk sizes and some extra
      // allowance. This way we achieve a smaller startup memory footprint.
      required = (startup_reservations[startup_index].chunk_size() +
                  2 * context_reservations[context_index].chunk_size()) +
                 Page::kObjectStartOffset;
      // Add a small allowance to the code space for small scripts.
      if (space == CODE_SPACE) required += 32 * KB;
    } else if (!FLAG_debug_code) {
      // We expect the vanilla snapshot to only require one page per space,
      // unless we are emitting debug code.
      DCHECK(!is_default_snapshot);
    }

    if (space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE) {
      uint32_t max_size =
          MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space));
      sizes_out[space - FIRST_PAGED_SPACE] = Min(required, max_size);
    } else {
      DCHECK(single_chunk);
    }
    startup_index++;
    context_index++;
  }

  DCHECK_EQ(startup_reservations.length(), startup_index);
  DCHECK_EQ(context_reservations.length(), context_index);
}


v8::StartupData Snapshot::CreateSnapshotBlob(
    const i::StartupSerializer& startup_ser,
    const i::PartialSerializer& context_ser, Snapshot::Metadata metadata) {
  SnapshotData startup_snapshot(startup_ser);
  SnapshotData context_snapshot(context_ser);
  Vector<const byte> startup_data = startup_snapshot.RawData();
  Vector<const byte> context_data = context_snapshot.RawData();

  uint32_t first_page_sizes[kNumPagedSpaces];

  CalculateFirstPageSizes(!metadata.embeds_script(), startup_snapshot,
                          context_snapshot, first_page_sizes);

  int startup_length = startup_data.length();
  int context_length = context_data.length();
  int context_offset = ContextOffset(startup_length);

  int length = context_offset + context_length;
  char* data = new char[length];

  memcpy(data + kMetadataOffset, &metadata.RawValue(), kInt32Size);
  memcpy(data + kFirstPageSizesOffset, first_page_sizes,
         kNumPagedSpaces * kInt32Size);
  memcpy(data + kStartupLengthOffset, &startup_length, kInt32Size);
  memcpy(data + kStartupDataOffset, startup_data.begin(), startup_length);
  memcpy(data + context_offset, context_data.begin(), context_length);
  v8::StartupData result = {data, length};

  if (FLAG_profile_deserialization) {
    PrintF(
        "Snapshot blob consists of:\n"
        "%10d bytes for startup\n"
        "%10d bytes for context\n",
        startup_length, context_length);
  }
  return result;
}


Snapshot::Metadata Snapshot::ExtractMetadata(const v8::StartupData* data) {
  uint32_t raw;
  memcpy(&raw, data->data + kMetadataOffset, kInt32Size);
  return Metadata(raw);
}


Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
  DCHECK_LT(kIntSize, data->raw_size);
  int startup_length;
  memcpy(&startup_length, data->data + kStartupLengthOffset, kInt32Size);
  DCHECK_LT(startup_length, data->raw_size);
  const byte* startup_data =
      reinterpret_cast<const byte*>(data->data + kStartupDataOffset);
  return Vector<const byte>(startup_data, startup_length);
}


Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data) {
  DCHECK_LT(kIntSize, data->raw_size);
  int startup_length;
  memcpy(&startup_length, data->data + kStartupLengthOffset, kIntSize);
  int context_offset = ContextOffset(startup_length);
  const byte* context_data =
      reinterpret_cast<const byte*>(data->data + context_offset);
  DCHECK_LT(context_offset, data->raw_size);
  int context_length = data->raw_size - context_offset;
  return Vector<const byte>(context_data, context_length);
}

SnapshotData::SnapshotData(const Serializer& ser) {
  DisallowHeapAllocation no_gc;
  List<Reservation> reservations;
  ser.EncodeReservations(&reservations);
  const List<byte>& payload = ser.sink()->data();

  // Calculate sizes.
  int reservation_size = reservations.length() * kInt32Size;
  int size = kHeaderSize + reservation_size + payload.length();

  // Allocate backing store and create result data.
  AllocateData(size);

  // Set header values.
  SetMagicNumber(ser.isolate());
  SetHeaderValue(kCheckSumOffset, Version::Hash());
  SetHeaderValue(kNumReservationsOffset, reservations.length());
  SetHeaderValue(kPayloadLengthOffset, payload.length());

  // Copy reservation chunk sizes.
  CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
            reservation_size);

  // Copy serialized data.
  CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(),
            static_cast<size_t>(payload.length()));
}

bool SnapshotData::IsSane() {
  return GetHeaderValue(kCheckSumOffset) == Version::Hash();
}

Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
  return Vector<const Reservation>(
      reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
      GetHeaderValue(kNumReservationsOffset));
}

Vector<const byte> SnapshotData::Payload() const {
  int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
  const byte* payload = data_ + kHeaderSize + reservations_size;
  int length = GetHeaderValue(kPayloadLengthOffset);
  DCHECK_EQ(data_ + size_, payload + length);
  return Vector<const byte>(payload, length);
}

}  // namespace internal
}  // namespace v8
