• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/objects/template-objects.h"
6 
7 #include "src/base/functional.h"
8 #include "src/execution/isolate.h"
9 #include "src/heap/factory.h"
10 #include "src/objects/objects-inl.h"
11 #include "src/objects/property-descriptor.h"
12 #include "src/objects/template-objects-inl.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // static
GetTemplateObject(Isolate * isolate,Handle<NativeContext> native_context,Handle<TemplateObjectDescription> description,Handle<SharedFunctionInfo> shared_info,int slot_id)18 Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
19     Isolate* isolate, Handle<NativeContext> native_context,
20     Handle<TemplateObjectDescription> description,
21     Handle<SharedFunctionInfo> shared_info, int slot_id) {
22   uint32_t hash = shared_info->Hash();
23 
24   // Check the template weakmap to see if the template object already exists.
25   Handle<EphemeronHashTable> template_weakmap;
26 
27   if (native_context->template_weakmap().IsUndefined(isolate)) {
28     template_weakmap = EphemeronHashTable::New(isolate, 1);
29   } else {
30     DisallowGarbageCollection no_gc;
31     ReadOnlyRoots roots(isolate);
32     template_weakmap = handle(
33         EphemeronHashTable::cast(native_context->template_weakmap()), isolate);
34     Object maybe_cached_template = template_weakmap->Lookup(shared_info, hash);
35     while (!maybe_cached_template.IsTheHole(roots)) {
36       CachedTemplateObject cached_template =
37           CachedTemplateObject::cast(maybe_cached_template);
38       if (cached_template.slot_id() == slot_id) {
39         return handle(cached_template.template_object(), isolate);
40       }
41       maybe_cached_template = cached_template.next();
42     }
43   }
44 
45   // Create the raw object from the {raw_strings}.
46   Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
47   Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
48       raw_strings, PACKED_ELEMENTS, raw_strings->length(),
49       AllocationType::kOld);
50 
51   // Create the template object from the {cooked_strings}.
52   Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
53   Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements(
54       cooked_strings, PACKED_ELEMENTS, cooked_strings->length(),
55       AllocationType::kOld);
56 
57   // Freeze the {raw_object}.
58   JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();
59 
60   // Install a "raw" data property for {raw_object} on {template_object}.
61   PropertyDescriptor raw_desc;
62   raw_desc.set_value(raw_object);
63   raw_desc.set_configurable(false);
64   raw_desc.set_enumerable(false);
65   raw_desc.set_writable(false);
66   JSArray::DefineOwnProperty(isolate, template_object,
67                              isolate->factory()->raw_string(), &raw_desc,
68                              Just(kThrowOnError))
69       .ToChecked();
70 
71   // Freeze the {template_object} as well.
72   JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
73       .ToChecked();
74 
75   // Insert the template object into the template weakmap.
76   Handle<HeapObject> previous_cached_templates = handle(
77       HeapObject::cast(template_weakmap->Lookup(shared_info, hash)), isolate);
78   Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New(
79       isolate, slot_id, template_object, previous_cached_templates);
80   template_weakmap = EphemeronHashTable::Put(
81       isolate, template_weakmap, shared_info, cached_template, hash);
82   native_context->set_template_weakmap(*template_weakmap);
83 
84   return template_object;
85 }
86 
New(Isolate * isolate,int slot_id,Handle<JSArray> template_object,Handle<HeapObject> next)87 Handle<CachedTemplateObject> CachedTemplateObject::New(
88     Isolate* isolate, int slot_id, Handle<JSArray> template_object,
89     Handle<HeapObject> next) {
90   DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
91   Handle<CachedTemplateObject> result_handle =
92       Handle<CachedTemplateObject>::cast(isolate->factory()->NewStruct(
93           CACHED_TEMPLATE_OBJECT_TYPE, AllocationType::kOld));
94   {
95     DisallowGarbageCollection no_gc;
96     auto result = *result_handle;
97     result.set_slot_id(slot_id);
98     result.set_template_object(*template_object);
99     result.set_next(*next);
100   }
101   return result_handle;
102 }
103 
104 }  // namespace internal
105 }  // namespace v8
106