Line data Source code
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/factory.h"
8 : #include "src/isolate.h"
9 : #include "src/objects-inl.h"
10 : #include "src/property-descriptor.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 3961 : bool TemplateObjectDescription::Equals(
16 : TemplateObjectDescription const* that) const {
17 3961 : if (this->raw_strings()->length() == that->raw_strings()->length()) {
18 3781 : for (int i = this->raw_strings()->length(); --i >= 0;) {
19 2819 : if (this->raw_strings()->get(i) != that->raw_strings()->get(i)) {
20 : return false;
21 : }
22 : }
23 : return true;
24 : }
25 : return false;
26 : }
27 :
28 : // static
29 2592 : Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
30 : Handle<TemplateObjectDescription> description,
31 : Handle<Context> native_context) {
32 : DCHECK(native_context->IsNativeContext());
33 : Isolate* const isolate = native_context->GetIsolate();
34 :
35 : // Check if we already have a [[TemplateMap]] for the {native_context},
36 : // and if not, just allocate one on the fly (which will be set below).
37 : Handle<TemplateMap> template_map =
38 : native_context->template_map()->IsUndefined(isolate)
39 : ? TemplateMap::New(isolate)
40 2592 : : handle(TemplateMap::cast(native_context->template_map()), isolate);
41 :
42 : // Check if we already have an appropriate entry.
43 : Handle<JSArray> template_object;
44 2592 : if (!TemplateMap::Lookup(template_map, description)
45 5184 : .ToHandle(&template_object)) {
46 : // Create the raw object from the {raw_strings}.
47 : Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
48 : Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
49 1630 : raw_strings, PACKED_ELEMENTS, raw_strings->length(), TENURED);
50 :
51 : // Create the template object from the {cooked_strings}.
52 : Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
53 : template_object = isolate->factory()->NewJSArrayWithElements(
54 1630 : cooked_strings, PACKED_ELEMENTS, cooked_strings->length(), TENURED);
55 :
56 : // Freeze the {raw_object}.
57 1630 : JSObject::SetIntegrityLevel(raw_object, FROZEN, Object::THROW_ON_ERROR)
58 3260 : .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 1630 : Object::THROW_ON_ERROR)
69 3260 : .ToChecked();
70 :
71 : // Freeze the {template_object} as well.
72 1630 : JSObject::SetIntegrityLevel(template_object, FROZEN, Object::THROW_ON_ERROR)
73 3260 : .ToChecked();
74 :
75 : // Remember the {template_object} in the {template_map}.
76 1630 : template_map = TemplateMap::Add(template_map, description, template_object);
77 : native_context->set_template_map(*template_map);
78 : }
79 :
80 2592 : return template_object;
81 : }
82 :
83 : // static
84 0 : bool TemplateMapShape::IsMatch(TemplateObjectDescription* key, Object* value) {
85 3961 : return key->Equals(TemplateObjectDescription::cast(value));
86 : }
87 :
88 : // static
89 0 : uint32_t TemplateMapShape::Hash(Isolate* isolate,
90 : TemplateObjectDescription* key) {
91 3871 : return key->hash();
92 : }
93 :
94 : // static
95 2241 : uint32_t TemplateMapShape::HashForObject(Isolate* isolate, Object* object) {
96 2241 : return Hash(isolate, TemplateObjectDescription::cast(object));
97 : }
98 :
99 : // static
100 0 : Handle<TemplateMap> TemplateMap::New(Isolate* isolate) {
101 64 : return HashTable::New(isolate, 0);
102 : }
103 :
104 : // static
105 2592 : MaybeHandle<JSArray> TemplateMap::Lookup(
106 : Handle<TemplateMap> template_map, Handle<TemplateObjectDescription> key) {
107 2592 : int const entry = template_map->FindEntry(*key);
108 2592 : if (entry == kNotFound) return MaybeHandle<JSArray>();
109 : int const index = EntryToIndex(entry);
110 1924 : return handle(JSArray::cast(template_map->get(index + 1)));
111 : }
112 :
113 : // static
114 1630 : Handle<TemplateMap> TemplateMap::Add(Handle<TemplateMap> template_map,
115 : Handle<TemplateObjectDescription> key,
116 : Handle<JSArray> value) {
117 : DCHECK_EQ(kNotFound, template_map->FindEntry(*key));
118 1630 : template_map = EnsureCapacity(template_map, 1);
119 : uint32_t const hash = ShapeT::Hash(key->GetIsolate(), *key);
120 1630 : int const entry = template_map->FindInsertionEntry(hash);
121 : int const index = EntryToIndex(entry);
122 1630 : template_map->set(index + 0, *key);
123 3260 : template_map->set(index + 1, *value);
124 1630 : template_map->ElementAdded();
125 1630 : return template_map;
126 : }
127 :
128 : } // namespace internal
129 : } // namespace v8
|