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/literal-objects.h"
6 :
7 : #include "src/accessors.h"
8 : #include "src/ast/ast.h"
9 : #include "src/heap/factory.h"
10 : #include "src/isolate.h"
11 : #include "src/objects-inl.h"
12 : #include "src/objects/hash-table-inl.h"
13 : #include "src/objects/literal-objects-inl.h"
14 : #include "src/objects/smi.h"
15 : #include "src/objects/struct-inl.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 4650826 : Object ObjectBoilerplateDescription::name(int index) const {
21 : // get() already checks for out of bounds access, but we do not want to allow
22 : // access to the last element, if it is the number of properties.
23 : DCHECK_NE(size(), index);
24 9301652 : return get(2 * index + kDescriptionStartIndex);
25 : }
26 :
27 4650829 : Object ObjectBoilerplateDescription::value(int index) const {
28 9301657 : return get(2 * index + 1 + kDescriptionStartIndex);
29 : }
30 :
31 1960429 : void ObjectBoilerplateDescription::set_key_value(int index, Object key,
32 : Object value) {
33 : DCHECK_LT(index, size());
34 : DCHECK_GE(index, 0);
35 1960429 : set(2 * index + kDescriptionStartIndex, key);
36 1960429 : set(2 * index + 1 + kDescriptionStartIndex, value);
37 1960429 : }
38 :
39 376001 : int ObjectBoilerplateDescription::size() const {
40 : DCHECK_EQ(0, (length() - kDescriptionStartIndex -
41 : (this->has_number_of_properties() ? 1 : 0)) %
42 : 2);
43 : // Rounding is intended.
44 732421 : return (length() - kDescriptionStartIndex) / 2;
45 : }
46 :
47 361391 : int ObjectBoilerplateDescription::backing_store_size() const {
48 361391 : if (has_number_of_properties()) {
49 : // If present, the last entry contains the number of properties.
50 4971 : return Smi::ToInt(this->get(length() - 1));
51 : }
52 : // If the number is not given explicitly, we assume there are no
53 : // properties with computed names.
54 356420 : return size();
55 : }
56 :
57 2751 : void ObjectBoilerplateDescription::set_backing_store_size(
58 : Isolate* isolate, int backing_store_size) {
59 : DCHECK(has_number_of_properties());
60 : DCHECK_NE(size(), backing_store_size);
61 : Handle<Object> backing_store_size_obj =
62 2751 : isolate->factory()->NewNumberFromInt(backing_store_size);
63 2751 : set(length() - 1, *backing_store_size_obj);
64 2751 : }
65 :
66 0 : bool ObjectBoilerplateDescription::has_number_of_properties() const {
67 361391 : return (length() - kDescriptionStartIndex) % 2 != 0;
68 : }
69 :
70 : namespace {
71 :
72 : inline int EncodeComputedEntry(ClassBoilerplate::ValueKind value_kind,
73 : unsigned key_index) {
74 : typedef ClassBoilerplate::ComputedEntryFlags Flags;
75 5528 : int flags = Flags::ValueKindBits::encode(value_kind) |
76 5528 : Flags::KeyIndexBits::encode(key_index);
77 : return flags;
78 : }
79 :
80 254394 : void AddToDescriptorArrayTemplate(
81 : Isolate* isolate, Handle<DescriptorArray> descriptor_array_template,
82 : Handle<Name> name, ClassBoilerplate::ValueKind value_kind,
83 : Handle<Object> value) {
84 763182 : int entry = descriptor_array_template->Search(
85 : *name, descriptor_array_template->number_of_descriptors());
86 : // TODO(ishell): deduplicate properties at AST level, this will allow us to
87 : // avoid creation of closures that will be overwritten anyway.
88 254394 : if (entry == DescriptorArray::kNotFound) {
89 : // Entry not found, add new one.
90 254216 : Descriptor d;
91 254216 : if (value_kind == ClassBoilerplate::kData) {
92 250976 : d = Descriptor::DataConstant(name, value, DONT_ENUM);
93 : } else {
94 : DCHECK(value_kind == ClassBoilerplate::kGetter ||
95 : value_kind == ClassBoilerplate::kSetter);
96 3240 : Handle<AccessorPair> pair = isolate->factory()->NewAccessorPair();
97 9720 : pair->set(value_kind == ClassBoilerplate::kGetter ? ACCESSOR_GETTER
98 : : ACCESSOR_SETTER,
99 3240 : *value);
100 3240 : d = Descriptor::AccessorConstant(name, pair, DONT_ENUM);
101 : }
102 254216 : descriptor_array_template->Append(&d);
103 :
104 : } else {
105 : // Entry found, update it.
106 356 : int sorted_index = descriptor_array_template->GetDetails(entry).pointer();
107 178 : if (value_kind == ClassBoilerplate::kData) {
108 36 : Descriptor d = Descriptor::DataConstant(name, value, DONT_ENUM);
109 : d.SetSortedKeyIndex(sorted_index);
110 36 : descriptor_array_template->Set(entry, &d);
111 : } else {
112 : DCHECK(value_kind == ClassBoilerplate::kGetter ||
113 : value_kind == ClassBoilerplate::kSetter);
114 142 : Object raw_accessor = descriptor_array_template->GetStrongValue(entry);
115 142 : AccessorPair pair;
116 142 : if (raw_accessor->IsAccessorPair()) {
117 118 : pair = AccessorPair::cast(raw_accessor);
118 : } else {
119 24 : Handle<AccessorPair> new_pair = isolate->factory()->NewAccessorPair();
120 24 : Descriptor d = Descriptor::AccessorConstant(name, new_pair, DONT_ENUM);
121 : d.SetSortedKeyIndex(sorted_index);
122 24 : descriptor_array_template->Set(entry, &d);
123 24 : pair = *new_pair;
124 : }
125 142 : pair->set(value_kind == ClassBoilerplate::kGetter ? ACCESSOR_GETTER
126 : : ACCESSOR_SETTER,
127 142 : *value);
128 : }
129 : }
130 254394 : }
131 :
132 : Handle<NameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
133 : Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
134 : Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
135 : return NameDictionary::AddNoUpdateNextEnumerationIndex(
136 35727 : isolate, dictionary, name, value, details, entry_out);
137 : }
138 :
139 : Handle<NumberDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
140 : Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t element,
141 : Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
142 : // NumberDictionary does not maintain the enumeration order, so it's
143 : // a normal Add().
144 : return NumberDictionary::Add(isolate, dictionary, element, value, details,
145 446 : entry_out);
146 : }
147 :
148 : void DictionaryUpdateMaxNumberKey(Handle<NameDictionary> dictionary,
149 : Handle<Name> name) {
150 : // No-op for name dictionaries.
151 : }
152 :
153 446 : void DictionaryUpdateMaxNumberKey(Handle<NumberDictionary> dictionary,
154 : uint32_t element) {
155 446 : dictionary->UpdateMaxNumberKey(element, Handle<JSObject>());
156 : dictionary->set_requires_slow_elements();
157 446 : }
158 :
159 : constexpr int ComputeEnumerationIndex(int value_index) {
160 : // We "shift" value indices to ensure that the enumeration index for the value
161 : // will not overlap with minimum properties set for both class and prototype
162 : // objects.
163 : return value_index + Max(ClassBoilerplate::kMinimumClassPropertiesCount,
164 56753 : ClassBoilerplate::kMinimumPrototypePropertiesCount);
165 : }
166 :
167 : inline int GetExistingValueIndex(Object value) {
168 255 : return value->IsSmi() ? Smi::ToInt(value) : -1;
169 : }
170 :
171 : template <typename Dictionary, typename Key>
172 27682 : void AddToDictionaryTemplate(Isolate* isolate, Handle<Dictionary> dictionary,
173 : Key key, int key_index,
174 : ClassBoilerplate::ValueKind value_kind,
175 : Object value) {
176 27682 : int entry = dictionary->FindEntry(isolate, key);
177 :
178 27682 : if (entry == kNotFound) {
179 : // Entry not found, add new one.
180 : const bool is_elements_dictionary =
181 : std::is_same<Dictionary, NumberDictionary>::value;
182 : STATIC_ASSERT(is_elements_dictionary !=
183 : (std::is_same<Dictionary, NameDictionary>::value));
184 : int enum_order =
185 : is_elements_dictionary ? 0 : ComputeEnumerationIndex(key_index);
186 : Handle<Object> value_handle;
187 : PropertyDetails details(
188 : value_kind != ClassBoilerplate::kData ? kAccessor : kData, DONT_ENUM,
189 27449 : PropertyCellType::kNoCell, enum_order);
190 :
191 27449 : if (value_kind == ClassBoilerplate::kData) {
192 : value_handle = handle(value, isolate);
193 : } else {
194 : AccessorComponent component = value_kind == ClassBoilerplate::kGetter
195 : ? ACCESSOR_GETTER
196 2800 : : ACCESSOR_SETTER;
197 2800 : Handle<AccessorPair> pair(isolate->factory()->NewAccessorPair());
198 2800 : pair->set(component, value);
199 : value_handle = pair;
200 : }
201 :
202 : // Add value to the dictionary without updating next enumeration index.
203 : Handle<Dictionary> dict = DictionaryAddNoUpdateNextEnumerationIndex(
204 : isolate, dictionary, key, value_handle, details, &entry);
205 : // It is crucial to avoid dictionary reallocations because it may remove
206 : // potential gaps in enumeration indices values that are necessary for
207 : // inserting computed properties into right places in the enumeration order.
208 27449 : CHECK_EQ(*dict, *dictionary);
209 :
210 446 : DictionaryUpdateMaxNumberKey(dictionary, key);
211 :
212 : } else {
213 : // Entry found, update it.
214 : int enum_order = dictionary->DetailsAt(entry).dictionary_index();
215 466 : Object existing_value = dictionary->ValueAt(entry);
216 233 : if (value_kind == ClassBoilerplate::kData) {
217 : // Computed value is a normal method.
218 90 : if (existing_value->IsAccessorPair()) {
219 72 : AccessorPair current_pair = AccessorPair::cast(existing_value);
220 :
221 : int existing_getter_index =
222 : GetExistingValueIndex(current_pair->getter());
223 : int existing_setter_index =
224 : GetExistingValueIndex(current_pair->setter());
225 : // At least one of the accessors must already be defined.
226 : DCHECK(existing_getter_index >= 0 || existing_setter_index >= 0);
227 72 : if (existing_getter_index < key_index &&
228 : existing_setter_index < key_index) {
229 : // Either both getter and setter were defined before the computed
230 : // method or just one of them was defined before while the other one
231 : // was not defined yet, so overwrite property to kData.
232 : PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell,
233 : enum_order);
234 0 : dictionary->DetailsAtPut(isolate, entry, details);
235 0 : dictionary->ValueAtPut(entry, value);
236 :
237 : } else {
238 : // The data property was defined "between" accessors so the one that
239 : // was overwritten has to be cleared.
240 72 : if (existing_getter_index < key_index) {
241 : DCHECK_LT(key_index, existing_setter_index);
242 : // Getter was defined and it was done before the computed method
243 : // and then it was overwritten by the current computed method which
244 : // in turn was later overwritten by the setter method. So we clear
245 : // the getter.
246 36 : current_pair->set_getter(*isolate->factory()->null_value());
247 :
248 36 : } else if (existing_setter_index < key_index) {
249 : DCHECK_LT(key_index, existing_getter_index);
250 : // Setter was defined and it was done before the computed method
251 : // and then it was overwritten by the current computed method which
252 : // in turn was later overwritten by the getter method. So we clear
253 : // the setter.
254 36 : current_pair->set_setter(*isolate->factory()->null_value());
255 : }
256 : }
257 : } else {
258 : // Overwrite existing value if it was defined before the computed one.
259 : int existing_value_index = Smi::ToInt(existing_value);
260 18 : if (existing_value_index < key_index) {
261 : PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell,
262 : enum_order);
263 18 : dictionary->DetailsAtPut(isolate, entry, details);
264 54 : dictionary->ValueAtPut(entry, value);
265 : }
266 : }
267 : } else {
268 : AccessorComponent component = value_kind == ClassBoilerplate::kGetter
269 : ? ACCESSOR_GETTER
270 143 : : ACCESSOR_SETTER;
271 143 : if (existing_value->IsAccessorPair()) {
272 111 : AccessorPair current_pair = AccessorPair::cast(existing_value);
273 :
274 : int existing_component_index =
275 111 : GetExistingValueIndex(current_pair->get(component));
276 111 : if (existing_component_index < key_index) {
277 93 : current_pair->set(component, value);
278 : }
279 :
280 : } else {
281 32 : Handle<AccessorPair> pair(isolate->factory()->NewAccessorPair());
282 32 : pair->set(component, value);
283 : PropertyDetails details(kAccessor, DONT_ENUM, PropertyCellType::kNoCell,
284 : enum_order);
285 32 : dictionary->DetailsAtPut(isolate, entry, details);
286 96 : dictionary->ValueAtPut(entry, *pair);
287 : }
288 : }
289 : }
290 27682 : }
291 :
292 : } // namespace
293 :
294 : // Helper class that eases building of a properties, elements and computed
295 : // properties templates.
296 80192 : class ObjectDescriptor {
297 : public:
298 5908 : void IncComputedCount() { ++computed_count_; }
299 279223 : void IncPropertiesCount() { ++property_count_; }
300 155 : void IncElementsCount() { ++element_count_; }
301 :
302 : bool HasDictionaryProperties() const {
303 812132 : return computed_count_ > 0 || property_count_ > kMaxNumberOfDescriptors;
304 : }
305 :
306 : Handle<Object> properties_template() const {
307 : return HasDictionaryProperties()
308 : ? Handle<Object>::cast(properties_dictionary_template_)
309 80192 : : Handle<Object>::cast(descriptor_array_template_);
310 : }
311 :
312 : Handle<NumberDictionary> elements_template() const {
313 : return elements_dictionary_template_;
314 : }
315 :
316 : Handle<FixedArray> computed_properties() const {
317 : return computed_properties_;
318 : }
319 :
320 80192 : void CreateTemplates(Isolate* isolate, int slack) {
321 : Factory* factory = isolate->factory();
322 80192 : descriptor_array_template_ = factory->empty_descriptor_array();
323 80192 : properties_dictionary_template_ = factory->empty_property_dictionary();
324 140477 : if (property_count_ || HasDictionaryProperties() || slack) {
325 80192 : if (HasDictionaryProperties()) {
326 : properties_dictionary_template_ = NameDictionary::New(
327 5596 : isolate, property_count_ + computed_count_ + slack);
328 : } else {
329 : descriptor_array_template_ =
330 74596 : DescriptorArray::Allocate(isolate, 0, property_count_ + slack);
331 : }
332 : }
333 : elements_dictionary_template_ =
334 80192 : element_count_ || computed_count_
335 5624 : ? NumberDictionary::New(isolate, element_count_ + computed_count_)
336 160384 : : factory->empty_slow_element_dictionary();
337 :
338 : computed_properties_ =
339 80192 : computed_count_
340 : ? factory->NewFixedArray(computed_count_ *
341 5584 : ClassBoilerplate::kFullComputedEntrySize)
342 160384 : : factory->empty_fixed_array();
343 :
344 80192 : temp_handle_ = handle(Smi::kZero, isolate);
345 80192 : }
346 :
347 196159 : void AddConstant(Isolate* isolate, Handle<Name> name, Handle<Object> value,
348 : PropertyAttributes attribs) {
349 : bool is_accessor = value->IsAccessorInfo();
350 : DCHECK(!value->IsAccessorPair());
351 196159 : if (HasDictionaryProperties()) {
352 8724 : PropertyKind kind = is_accessor ? i::kAccessor : i::kData;
353 : PropertyDetails details(kind, attribs, PropertyCellType::kNoCell,
354 8724 : next_enumeration_index_++);
355 : properties_dictionary_template_ =
356 : DictionaryAddNoUpdateNextEnumerationIndex(
357 8724 : isolate, properties_dictionary_template_, name, value, details);
358 : } else {
359 : Descriptor d = is_accessor
360 : ? Descriptor::AccessorConstant(name, value, attribs)
361 187435 : : Descriptor::DataConstant(name, value, attribs);
362 187435 : descriptor_array_template_->Append(&d);
363 : }
364 196159 : }
365 :
366 278616 : void AddNamedProperty(Isolate* isolate, Handle<Name> name,
367 : ClassBoilerplate::ValueKind value_kind,
368 : int value_index) {
369 : Smi value = Smi::FromInt(value_index);
370 278616 : if (HasDictionaryProperties()) {
371 : UpdateNextEnumerationIndex(value_index);
372 : AddToDictionaryTemplate(isolate, properties_dictionary_template_, name,
373 24222 : value_index, value_kind, value);
374 : } else {
375 254394 : *temp_handle_.location() = value->ptr();
376 : AddToDescriptorArrayTemplate(isolate, descriptor_array_template_, name,
377 254394 : value_kind, temp_handle_);
378 : }
379 278616 : }
380 :
381 : void AddIndexedProperty(Isolate* isolate, uint32_t element,
382 : ClassBoilerplate::ValueKind value_kind,
383 : int value_index) {
384 155 : Smi value = Smi::FromInt(value_index);
385 : AddToDictionaryTemplate(isolate, elements_dictionary_template_, element,
386 155 : value_index, value_kind, value);
387 : }
388 :
389 5528 : void AddComputed(ClassBoilerplate::ValueKind value_kind, int key_index) {
390 : int value_index = key_index + 1;
391 : UpdateNextEnumerationIndex(value_index);
392 :
393 5528 : int flags = EncodeComputedEntry(value_kind, key_index);
394 5528 : computed_properties_->set(current_computed_index_++, Smi::FromInt(flags));
395 5528 : }
396 :
397 : void UpdateNextEnumerationIndex(int value_index) {
398 : int next_index = ComputeEnumerationIndex(value_index);
399 : DCHECK_LT(next_enumeration_index_, next_index);
400 29750 : next_enumeration_index_ = next_index;
401 : }
402 :
403 80192 : void Finalize(Isolate* isolate) {
404 80192 : if (HasDictionaryProperties()) {
405 5596 : properties_dictionary_template_->SetNextEnumerationIndex(
406 : next_enumeration_index_);
407 : computed_properties_ = FixedArray::ShrinkOrEmpty(
408 5596 : isolate, computed_properties_, current_computed_index_);
409 : } else {
410 : DCHECK(descriptor_array_template_->IsSortedNoDuplicates());
411 : }
412 80192 : }
413 :
414 : private:
415 : int property_count_ = 0;
416 : int next_enumeration_index_ = PropertyDetails::kInitialIndex;
417 : int element_count_ = 0;
418 : int computed_count_ = 0;
419 : int current_computed_index_ = 0;
420 :
421 : Handle<DescriptorArray> descriptor_array_template_;
422 : Handle<NameDictionary> properties_dictionary_template_;
423 : Handle<NumberDictionary> elements_dictionary_template_;
424 : Handle<FixedArray> computed_properties_;
425 : // This temporary handle is used for storing to descriptor array.
426 : Handle<Object> temp_handle_;
427 : };
428 :
429 2999 : void ClassBoilerplate::AddToPropertiesTemplate(
430 : Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
431 : int key_index, ClassBoilerplate::ValueKind value_kind, Object value) {
432 : AddToDictionaryTemplate(isolate, dictionary, name, key_index, value_kind,
433 2999 : value);
434 2999 : }
435 :
436 306 : void ClassBoilerplate::AddToElementsTemplate(
437 : Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
438 : int key_index, ClassBoilerplate::ValueKind value_kind, Object value) {
439 : AddToDictionaryTemplate(isolate, dictionary, key, key_index, value_kind,
440 306 : value);
441 306 : }
442 :
443 40096 : Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
444 : Isolate* isolate, ClassLiteral* expr) {
445 : // Create a non-caching handle scope to ensure that the temporary handle used
446 : // by ObjectDescriptor for passing Smis around does not corrupt handle cache
447 : // in CanonicalHandleScope.
448 : HandleScope scope(isolate);
449 : Factory* factory = isolate->factory();
450 : ObjectDescriptor static_desc;
451 : ObjectDescriptor instance_desc;
452 :
453 610668 : for (int i = 0; i < expr->properties()->length(); i++) {
454 285286 : ClassLiteral::Property* property = expr->properties()->at(i);
455 : ObjectDescriptor& desc =
456 285286 : property->is_static() ? static_desc : instance_desc;
457 285286 : if (property->is_computed_name()) {
458 : desc.IncComputedCount();
459 : } else {
460 558756 : if (property->key()->AsLiteral()->IsPropertyName()) {
461 : desc.IncPropertiesCount();
462 : } else {
463 : desc.IncElementsCount();
464 : }
465 : }
466 : }
467 :
468 : //
469 : // Initialize class object template.
470 : //
471 40096 : static_desc.CreateTemplates(isolate, kMinimumClassPropertiesCount);
472 : STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
473 : {
474 : // Add length_accessor.
475 : PropertyAttributes attribs =
476 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
477 40096 : static_desc.AddConstant(isolate, factory->length_string(),
478 40096 : factory->function_length_accessor(), attribs);
479 : }
480 : {
481 : // Add prototype_accessor.
482 : PropertyAttributes attribs =
483 : static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
484 40096 : static_desc.AddConstant(isolate, factory->prototype_string(),
485 40096 : factory->function_prototype_accessor(), attribs);
486 : }
487 40096 : if (FunctionLiteral::NeedsHomeObject(expr->constructor())) {
488 : PropertyAttributes attribs =
489 : static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
490 : Handle<Object> value(
491 : Smi::FromInt(ClassBoilerplate::kPrototypeArgumentIndex), isolate);
492 828 : static_desc.AddConstant(isolate, factory->home_object_symbol(), value,
493 828 : attribs);
494 : }
495 : {
496 : Handle<ClassPositions> class_positions = factory->NewClassPositions(
497 40096 : expr->start_position(), expr->end_position());
498 40096 : static_desc.AddConstant(isolate, factory->class_positions_symbol(),
499 40096 : class_positions, DONT_ENUM);
500 : }
501 :
502 : //
503 : // Initialize prototype object template.
504 : //
505 40096 : instance_desc.CreateTemplates(isolate, kMinimumPrototypePropertiesCount);
506 : {
507 : Handle<Object> value(
508 : Smi::FromInt(ClassBoilerplate::kConstructorArgumentIndex), isolate);
509 40096 : instance_desc.AddConstant(isolate, factory->constructor_string(), value,
510 40096 : DONT_ENUM);
511 : }
512 :
513 : //
514 : // Fill in class boilerplate.
515 : //
516 : int dynamic_argument_index = ClassBoilerplate::kFirstDynamicArgumentIndex;
517 :
518 610668 : for (int i = 0; i < expr->properties()->length(); i++) {
519 285286 : ClassLiteral::Property* property = expr->properties()->at(i);
520 :
521 : ClassBoilerplate::ValueKind value_kind;
522 285286 : switch (property->kind()) {
523 : case ClassLiteral::Property::METHOD:
524 : value_kind = ClassBoilerplate::kData;
525 277950 : break;
526 : case ClassLiteral::Property::GETTER:
527 : value_kind = ClassBoilerplate::kGetter;
528 3388 : break;
529 : case ClassLiteral::Property::SETTER:
530 : value_kind = ClassBoilerplate::kSetter;
531 2961 : break;
532 : case ClassLiteral::Property::FIELD:
533 : DCHECK_IMPLIES(property->is_computed_name(), !property->is_private());
534 987 : if (property->is_computed_name()) {
535 380 : ++dynamic_argument_index;
536 : }
537 6515 : continue;
538 : }
539 :
540 : ObjectDescriptor& desc =
541 284299 : property->is_static() ? static_desc : instance_desc;
542 284299 : if (property->is_computed_name()) {
543 : int computed_name_index = dynamic_argument_index;
544 5528 : dynamic_argument_index += 2; // Computed name and value indices.
545 5528 : desc.AddComputed(value_kind, computed_name_index);
546 5528 : continue;
547 : }
548 278771 : int value_index = dynamic_argument_index++;
549 :
550 278771 : Literal* key_literal = property->key()->AsLiteral();
551 : uint32_t index;
552 278771 : if (key_literal->AsArrayIndex(&index)) {
553 155 : desc.AddIndexedProperty(isolate, index, value_kind, value_index);
554 :
555 : } else {
556 : Handle<String> name = key_literal->AsRawPropertyName()->string();
557 : DCHECK(name->IsInternalizedString());
558 278616 : desc.AddNamedProperty(isolate, name, value_kind, value_index);
559 : }
560 : }
561 :
562 : // Add name accessor to the class object if necessary.
563 : bool install_class_name_accessor = false;
564 40096 : if (!expr->has_name_static_property() &&
565 : expr->constructor()->has_shared_name()) {
566 36496 : if (static_desc.HasDictionaryProperties()) {
567 : // Install class name accessor if necessary during class literal
568 : // instantiation.
569 : install_class_name_accessor = true;
570 : } else {
571 : // Set class name accessor if the "name" method was not added yet.
572 : PropertyAttributes attribs =
573 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
574 34947 : static_desc.AddConstant(isolate, factory->name_string(),
575 34947 : factory->function_name_accessor(), attribs);
576 : }
577 : }
578 :
579 40096 : static_desc.Finalize(isolate);
580 40096 : instance_desc.Finalize(isolate);
581 :
582 : Handle<ClassBoilerplate> class_boilerplate =
583 40096 : Handle<ClassBoilerplate>::cast(factory->NewFixedArray(kBoileplateLength));
584 :
585 : class_boilerplate->set_flags(0);
586 120288 : class_boilerplate->set_install_class_name_accessor(
587 40096 : install_class_name_accessor);
588 40096 : class_boilerplate->set_arguments_count(dynamic_argument_index);
589 :
590 80192 : class_boilerplate->set_static_properties_template(
591 40096 : *static_desc.properties_template());
592 120288 : class_boilerplate->set_static_elements_template(
593 40096 : *static_desc.elements_template());
594 80192 : class_boilerplate->set_static_computed_properties(
595 40096 : *static_desc.computed_properties());
596 :
597 80192 : class_boilerplate->set_instance_properties_template(
598 40096 : *instance_desc.properties_template());
599 120288 : class_boilerplate->set_instance_elements_template(
600 40096 : *instance_desc.elements_template());
601 80192 : class_boilerplate->set_instance_computed_properties(
602 40096 : *instance_desc.computed_properties());
603 :
604 80192 : return scope.CloseAndEscape(class_boilerplate);
605 : }
606 :
607 : } // namespace internal
608 120216 : } // namespace v8
|