// 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/object-deserializer.h"

#include "src/codegen/assembler-inl.h"
#include "src/execution/isolate.h"
#include "src/heap/heap-inl.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/objects.h"
#include "src/objects/slots.h"
#include "src/snapshot/code-serializer.h"

namespace v8 {
namespace internal {

ObjectDeserializer::ObjectDeserializer(const SerializedCodeData* data)
    : Deserializer(data, true) {}

MaybeHandle<SharedFunctionInfo>
ObjectDeserializer::DeserializeSharedFunctionInfo(
    Isolate* isolate, const SerializedCodeData* data, Handle<String> source) {
  ObjectDeserializer d(data);

  d.AddAttachedObject(source);

  Handle<HeapObject> result;
  return d.Deserialize(isolate).ToHandle(&result)
             ? Handle<SharedFunctionInfo>::cast(result)
             : MaybeHandle<SharedFunctionInfo>();
}

MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) {
  Initialize(isolate);

  if (!allocator()->ReserveSpace()) return MaybeHandle<HeapObject>();

  DCHECK(deserializing_user_code());
  HandleScope scope(isolate);
  Handle<HeapObject> result;
  {
    DisallowHeapAllocation no_gc;
    Object root;
    VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
                     FullObjectSlot(&root));
    DeserializeDeferredObjects();
    FlushICache();
    LinkAllocationSites();
    LogNewMapEvents();
    result = handle(HeapObject::cast(root), isolate);
    Rehash();
    allocator()->RegisterDeserializedObjectsForBlackAllocation();
  }
  CommitPostProcessedObjects();
  return scope.CloseAndEscape(result);
}

void ObjectDeserializer::FlushICache() {
  DCHECK(deserializing_user_code());
  for (Code code : new_code_objects()) {
    // Record all references to embedded objects in the new code object.
    WriteBarrierForCode(code);
    FlushInstructionCache(code.raw_instruction_start(),
                          code.raw_instruction_size());
  }
}

void ObjectDeserializer::CommitPostProcessedObjects() {
  CHECK_LE(new_internalized_strings().size(), kMaxInt);
  StringTable::EnsureCapacityForDeserialization(
      isolate(), static_cast<int>(new_internalized_strings().size()));
  for (Handle<String> string : new_internalized_strings()) {
    DisallowHeapAllocation no_gc;
    StringTableInsertionKey key(*string);
    StringTable::AddKeyNoResize(isolate(), &key);
  }

  Heap* heap = isolate()->heap();
  Factory* factory = isolate()->factory();
  for (Handle<Script> script : new_scripts()) {
    // Assign a new script id to avoid collision.
    script->set_id(isolate()->heap()->NextScriptId());
    LogScriptEvents(*script);
    // Add script to list.
    Handle<WeakArrayList> list = factory->script_list();
    list = WeakArrayList::AddToEnd(isolate(), list,
                                   MaybeObjectHandle::Weak(script));
    heap->SetRootScriptList(*list);
  }
}

void ObjectDeserializer::LinkAllocationSites() {
  DisallowHeapAllocation no_gc;
  Heap* heap = isolate()->heap();
  // Allocation sites are present in the snapshot, and must be linked into
  // a list at deserialization time.
  for (AllocationSite site : new_allocation_sites()) {
    if (!site.HasWeakNext()) continue;
    // TODO(mvstanton): consider treating the heap()->allocation_sites_list()
    // as a (weak) root. If this root is relocated correctly, this becomes
    // unnecessary.
    if (heap->allocation_sites_list() == Smi::kZero) {
      site.set_weak_next(ReadOnlyRoots(heap).undefined_value());
    } else {
      site.set_weak_next(heap->allocation_sites_list());
    }
    heap->set_allocation_sites_list(site);
  }
}

}  // namespace internal
}  // namespace v8
