// Copyright 2017 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.

#include "src/snapshot/partial-deserializer.h"

#include "src/api.h"
#include "src/heap/heap-inl.h"
#include "src/snapshot/snapshot.h"

namespace v8 {
namespace internal {

MaybeHandle<Context> PartialDeserializer::DeserializeContext(
    Isolate* isolate, const SnapshotData* data, bool can_rehash,
    Handle<JSGlobalProxy> global_proxy,
    v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
  PartialDeserializer d(data);
  d.SetRehashability(can_rehash);

  MaybeHandle<Object> maybe_result =
      d.Deserialize(isolate, global_proxy, embedder_fields_deserializer);

  Handle<Object> result;
  return maybe_result.ToHandle(&result) ? Handle<Context>::cast(result)
                                        : MaybeHandle<Context>();
}

MaybeHandle<Object> PartialDeserializer::Deserialize(
    Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
    v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
  Initialize(isolate);
  if (!allocator()->ReserveSpace()) {
    V8::FatalProcessOutOfMemory("PartialDeserializer");
  }

  AddAttachedObject(global_proxy);

  DisallowHeapAllocation no_gc;
  // Keep track of the code space start and end pointers in case new
  // code objects were unserialized
  OldSpace* code_space = isolate->heap()->code_space();
  Address start_address = code_space->top();
  Object* root;
  VisitRootPointer(Root::kPartialSnapshotCache, &root);
  DeserializeDeferredObjects();
  DeserializeEmbedderFields(embedder_fields_deserializer);

  allocator()->RegisterDeserializedObjectsForBlackAllocation();

  // There's no code deserialized here. If this assert fires then that's
  // changed and logging should be added to notify the profiler et al of the
  // new code, which also has to be flushed from instruction cache.
  CHECK_EQ(start_address, code_space->top());

  if (FLAG_rehash_snapshot && can_rehash()) Rehash();

  return Handle<Object>(root, isolate);
}

void PartialDeserializer::DeserializeEmbedderFields(
    v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
  if (!source()->HasMore() || source()->Get() != kEmbedderFieldsData) return;
  DisallowHeapAllocation no_gc;
  DisallowJavascriptExecution no_js(isolate());
  DisallowCompilation no_compile(isolate());
  DCHECK_NOT_NULL(embedder_fields_deserializer.callback);
  for (int code = source()->Get(); code != kSynchronize;
       code = source()->Get()) {
    HandleScope scope(isolate());
    int space = code & kSpaceMask;
    DCHECK_LE(space, kNumberOfSpaces);
    DCHECK_EQ(code - space, kNewObject);
    Handle<JSObject> obj(JSObject::cast(GetBackReferencedObject(space)),
                         isolate());
    int index = source()->GetInt();
    int size = source()->GetInt();
    // TODO(yangguo,jgruber): Turn this into a reusable shared buffer.
    byte* data = new byte[size];
    source()->CopyRaw(data, size);
    embedder_fields_deserializer.callback(v8::Utils::ToLocal(obj), index,
                                          {reinterpret_cast<char*>(data), size},
                                          embedder_fields_deserializer.data);
    delete[] data;
  }
}
}  // namespace internal
}  // namespace v8
