// 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/objects/template-objects.h"

#include "src/base/functional.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/objects/objects-inl.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/template-objects-inl.h"

namespace v8 {
namespace internal {

// static
Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
    Isolate* isolate, Handle<NativeContext> native_context,
    Handle<TemplateObjectDescription> description,
    Handle<SharedFunctionInfo> shared_info, int slot_id) {
  // Check the template weakmap to see if the template object already exists.
  Handle<EphemeronHashTable> template_weakmap =
      native_context->template_weakmap().IsUndefined(isolate)
          ? EphemeronHashTable::New(isolate, 0)
          : handle(EphemeronHashTable::cast(native_context->template_weakmap()),
                   isolate);

  uint32_t hash = shared_info->Hash();
  Object maybe_cached_template = template_weakmap->Lookup(shared_info, hash);
  while (!maybe_cached_template.IsTheHole()) {
    CachedTemplateObject cached_template =
        CachedTemplateObject::cast(maybe_cached_template);
    if (cached_template.slot_id() == slot_id)
      return handle(cached_template.template_object(), isolate);

    maybe_cached_template = cached_template.next();
  }

  // Create the raw object from the {raw_strings}.
  Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
  Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
      raw_strings, PACKED_ELEMENTS, raw_strings->length(),
      AllocationType::kOld);

  // Create the template object from the {cooked_strings}.
  Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
  Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements(
      cooked_strings, PACKED_ELEMENTS, cooked_strings->length(),
      AllocationType::kOld);

  // Freeze the {raw_object}.
  JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();

  // Install a "raw" data property for {raw_object} on {template_object}.
  PropertyDescriptor raw_desc;
  raw_desc.set_value(raw_object);
  raw_desc.set_configurable(false);
  raw_desc.set_enumerable(false);
  raw_desc.set_writable(false);
  JSArray::DefineOwnProperty(isolate, template_object,
                             isolate->factory()->raw_string(), &raw_desc,
                             Just(kThrowOnError))
      .ToChecked();

  // Freeze the {template_object} as well.
  JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
      .ToChecked();

  // Insert the template object into the template weakmap.
  Handle<HeapObject> previous_cached_templates = handle(
      HeapObject::cast(template_weakmap->Lookup(shared_info, hash)), isolate);
  Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New(
      isolate, slot_id, template_object, previous_cached_templates);
  template_weakmap = EphemeronHashTable::Put(
      isolate, template_weakmap, shared_info, cached_template, hash);
  native_context->set_template_weakmap(*template_weakmap);

  return template_object;
}

Handle<CachedTemplateObject> CachedTemplateObject::New(
    Isolate* isolate, int slot_id, Handle<JSArray> template_object,
    Handle<HeapObject> next) {
  DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
  Factory* factory = isolate->factory();
  Handle<CachedTemplateObject> result = Handle<CachedTemplateObject>::cast(
      factory->NewStruct(TUPLE3_TYPE, AllocationType::kOld));
  result->set_slot_id(slot_id);
  result->set_template_object(*template_object);
  result->set_next(*next);
  return result;
}

}  // namespace internal
}  // namespace v8
