11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/objects/template-objects.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/functional.h"
81cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
91cb0ef41Sopenharmony_ci#include "src/heap/factory.h"
101cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
111cb0ef41Sopenharmony_ci#include "src/objects/property-descriptor.h"
121cb0ef41Sopenharmony_ci#include "src/objects/template-objects-inl.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci// static
181cb0ef41Sopenharmony_ciHandle<JSArray> TemplateObjectDescription::GetTemplateObject(
191cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<NativeContext> native_context,
201cb0ef41Sopenharmony_ci    Handle<TemplateObjectDescription> description,
211cb0ef41Sopenharmony_ci    Handle<SharedFunctionInfo> shared_info, int slot_id) {
221cb0ef41Sopenharmony_ci  uint32_t hash = shared_info->Hash();
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  // Check the template weakmap to see if the template object already exists.
251cb0ef41Sopenharmony_ci  Handle<EphemeronHashTable> template_weakmap;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  if (native_context->template_weakmap().IsUndefined(isolate)) {
281cb0ef41Sopenharmony_ci    template_weakmap = EphemeronHashTable::New(isolate, 1);
291cb0ef41Sopenharmony_ci  } else {
301cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
311cb0ef41Sopenharmony_ci    ReadOnlyRoots roots(isolate);
321cb0ef41Sopenharmony_ci    template_weakmap = handle(
331cb0ef41Sopenharmony_ci        EphemeronHashTable::cast(native_context->template_weakmap()), isolate);
341cb0ef41Sopenharmony_ci    Object maybe_cached_template = template_weakmap->Lookup(shared_info, hash);
351cb0ef41Sopenharmony_ci    while (!maybe_cached_template.IsTheHole(roots)) {
361cb0ef41Sopenharmony_ci      CachedTemplateObject cached_template =
371cb0ef41Sopenharmony_ci          CachedTemplateObject::cast(maybe_cached_template);
381cb0ef41Sopenharmony_ci      if (cached_template.slot_id() == slot_id) {
391cb0ef41Sopenharmony_ci        return handle(cached_template.template_object(), isolate);
401cb0ef41Sopenharmony_ci      }
411cb0ef41Sopenharmony_ci      maybe_cached_template = cached_template.next();
421cb0ef41Sopenharmony_ci    }
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  // Create the raw object from the {raw_strings}.
461cb0ef41Sopenharmony_ci  Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
471cb0ef41Sopenharmony_ci  Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
481cb0ef41Sopenharmony_ci      raw_strings, PACKED_ELEMENTS, raw_strings->length(),
491cb0ef41Sopenharmony_ci      AllocationType::kOld);
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  // Create the template object from the {cooked_strings}.
521cb0ef41Sopenharmony_ci  Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
531cb0ef41Sopenharmony_ci  Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements(
541cb0ef41Sopenharmony_ci      cooked_strings, PACKED_ELEMENTS, cooked_strings->length(),
551cb0ef41Sopenharmony_ci      AllocationType::kOld);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  // Freeze the {raw_object}.
581cb0ef41Sopenharmony_ci  JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  // Install a "raw" data property for {raw_object} on {template_object}.
611cb0ef41Sopenharmony_ci  PropertyDescriptor raw_desc;
621cb0ef41Sopenharmony_ci  raw_desc.set_value(raw_object);
631cb0ef41Sopenharmony_ci  raw_desc.set_configurable(false);
641cb0ef41Sopenharmony_ci  raw_desc.set_enumerable(false);
651cb0ef41Sopenharmony_ci  raw_desc.set_writable(false);
661cb0ef41Sopenharmony_ci  JSArray::DefineOwnProperty(isolate, template_object,
671cb0ef41Sopenharmony_ci                             isolate->factory()->raw_string(), &raw_desc,
681cb0ef41Sopenharmony_ci                             Just(kThrowOnError))
691cb0ef41Sopenharmony_ci      .ToChecked();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // Freeze the {template_object} as well.
721cb0ef41Sopenharmony_ci  JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
731cb0ef41Sopenharmony_ci      .ToChecked();
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  // Insert the template object into the template weakmap.
761cb0ef41Sopenharmony_ci  Handle<HeapObject> previous_cached_templates = handle(
771cb0ef41Sopenharmony_ci      HeapObject::cast(template_weakmap->Lookup(shared_info, hash)), isolate);
781cb0ef41Sopenharmony_ci  Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New(
791cb0ef41Sopenharmony_ci      isolate, slot_id, template_object, previous_cached_templates);
801cb0ef41Sopenharmony_ci  template_weakmap = EphemeronHashTable::Put(
811cb0ef41Sopenharmony_ci      isolate, template_weakmap, shared_info, cached_template, hash);
821cb0ef41Sopenharmony_ci  native_context->set_template_weakmap(*template_weakmap);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  return template_object;
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciHandle<CachedTemplateObject> CachedTemplateObject::New(
881cb0ef41Sopenharmony_ci    Isolate* isolate, int slot_id, Handle<JSArray> template_object,
891cb0ef41Sopenharmony_ci    Handle<HeapObject> next) {
901cb0ef41Sopenharmony_ci  DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
911cb0ef41Sopenharmony_ci  Handle<CachedTemplateObject> result_handle =
921cb0ef41Sopenharmony_ci      Handle<CachedTemplateObject>::cast(isolate->factory()->NewStruct(
931cb0ef41Sopenharmony_ci          CACHED_TEMPLATE_OBJECT_TYPE, AllocationType::kOld));
941cb0ef41Sopenharmony_ci  {
951cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
961cb0ef41Sopenharmony_ci    auto result = *result_handle;
971cb0ef41Sopenharmony_ci    result.set_slot_id(slot_id);
981cb0ef41Sopenharmony_ci    result.set_template_object(*template_object);
991cb0ef41Sopenharmony_ci    result.set_next(*next);
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci  return result_handle;
1021cb0ef41Sopenharmony_ci}
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci}  // namespace internal
1051cb0ef41Sopenharmony_ci}  // namespace v8
106