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