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 // Check the template weakmap to see if the template object already exists.
23 Handle<EphemeronHashTable> template_weakmap =
24 native_context->template_weakmap().IsUndefined(isolate)
25 ? EphemeronHashTable::New(isolate, 0)
26 : handle(EphemeronHashTable::cast(native_context->template_weakmap()),
27 isolate);
28
29 uint32_t hash = shared_info->Hash();
30 Object maybe_cached_template = template_weakmap->Lookup(shared_info, hash);
31 while (!maybe_cached_template.IsTheHole()) {
32 CachedTemplateObject cached_template =
33 CachedTemplateObject::cast(maybe_cached_template);
34 if (cached_template.slot_id() == slot_id)
35 return handle(cached_template.template_object(), isolate);
36
37 maybe_cached_template = cached_template.next();
38 }
39
40 // Create the raw object from the {raw_strings}.
41 Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
42 Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
43 raw_strings, PACKED_ELEMENTS, raw_strings->length(),
44 AllocationType::kOld);
45
46 // Create the template object from the {cooked_strings}.
47 Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
48 Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements(
49 cooked_strings, PACKED_ELEMENTS, cooked_strings->length(),
50 AllocationType::kOld);
51
52 // Freeze the {raw_object}.
53 JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();
54
55 // Install a "raw" data property for {raw_object} on {template_object}.
56 PropertyDescriptor raw_desc;
57 raw_desc.set_value(raw_object);
58 raw_desc.set_configurable(false);
59 raw_desc.set_enumerable(false);
60 raw_desc.set_writable(false);
61 JSArray::DefineOwnProperty(isolate, template_object,
62 isolate->factory()->raw_string(), &raw_desc,
63 Just(kThrowOnError))
64 .ToChecked();
65
66 // Freeze the {template_object} as well.
67 JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
68 .ToChecked();
69
70 // Insert the template object into the template weakmap.
71 Handle<HeapObject> previous_cached_templates = handle(
72 HeapObject::cast(template_weakmap->Lookup(shared_info, hash)), isolate);
73 Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New(
74 isolate, slot_id, template_object, previous_cached_templates);
75 template_weakmap = EphemeronHashTable::Put(
76 isolate, template_weakmap, shared_info, cached_template, hash);
77 native_context->set_template_weakmap(*template_weakmap);
78
79 return template_object;
80 }
81
New(Isolate * isolate,int slot_id,Handle<JSArray> template_object,Handle<HeapObject> next)82 Handle<CachedTemplateObject> CachedTemplateObject::New(
83 Isolate* isolate, int slot_id, Handle<JSArray> template_object,
84 Handle<HeapObject> next) {
85 DCHECK(next->IsCachedTemplateObject() || next->IsTheHole());
86 Factory* factory = isolate->factory();
87 Handle<CachedTemplateObject> result = Handle<CachedTemplateObject>::cast(
88 factory->NewStruct(CACHED_TEMPLATE_OBJECT_TYPE, AllocationType::kOld));
89 result->set_slot_id(slot_id);
90 result->set_template_object(*template_object);
91 result->set_next(*next);
92 return result;
93 }
94
95 } // namespace internal
96 } // namespace v8
97