OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/keys.h" | 5 #include "src/keys.h" |
6 | 6 |
7 #include "src/elements.h" | 7 #include "src/elements.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 // |string_properties_| and |symbol_properties_| set. | 37 // |string_properties_| and |symbol_properties_| set. |
38 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); | 38 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); |
39 int insertion_index = 0; | 39 int insertion_index = 0; |
40 int string_properties_index = 0; | 40 int string_properties_index = 0; |
41 int symbol_properties_index = 0; | 41 int symbol_properties_index = 0; |
42 // String and Symbol lengths always come in pairs: | 42 // String and Symbol lengths always come in pairs: |
43 size_t max_level = level_lengths_.size() / 2; | 43 size_t max_level = level_lengths_.size() / 2; |
44 for (size_t level = 0; level < max_level; level++) { | 44 for (size_t level = 0; level < max_level; level++) { |
45 int num_string_properties = level_lengths_[level * 2]; | 45 int num_string_properties = level_lengths_[level * 2]; |
46 int num_symbol_properties = level_lengths_[level * 2 + 1]; | 46 int num_symbol_properties = level_lengths_[level * 2 + 1]; |
| 47 int num_elements = 0; |
47 if (num_string_properties < 0) { | 48 if (num_string_properties < 0) { |
48 // If the |num_string_properties| is negative, the current level contains | 49 // If the |num_string_properties| is negative, the current level contains |
49 // properties from a proxy, hence we skip the integer keys in |elements_| | 50 // properties from a proxy, hence we skip the integer keys in |elements_| |
50 // since proxies define the complete ordering. | 51 // since proxies define the complete ordering. |
51 num_string_properties = -num_string_properties; | 52 num_string_properties = -num_string_properties; |
52 } else if (level < elements_.size()) { | 53 } else if (level < elements_.size()) { |
53 // Add the element indices for this prototype level. | 54 // Add the element indices for this prototype level. |
54 std::vector<uint32_t>* elements = elements_[level]; | 55 std::vector<uint32_t>* elements = elements_[level]; |
55 int num_elements = static_cast<int>(elements->size()); | 56 num_elements = static_cast<int>(elements->size()); |
56 for (int i = 0; i < num_elements; i++) { | 57 for (int i = 0; i < num_elements; i++) { |
57 Handle<Object> key; | 58 Handle<Object> key; |
58 if (convert == KEEP_NUMBERS) { | 59 if (convert == KEEP_NUMBERS) { |
59 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); | 60 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); |
60 } else { | 61 } else { |
61 key = isolate_->factory()->Uint32ToString(elements->at(i)); | 62 key = isolate_->factory()->Uint32ToString(elements->at(i)); |
62 } | 63 } |
63 result->set(insertion_index, *key); | 64 result->set(insertion_index, *key); |
64 insertion_index++; | 65 insertion_index++; |
65 } | 66 } |
66 } | 67 } |
67 // Add the string property keys for this prototype level. | 68 // Add the string property keys for this prototype level. |
68 for (int i = 0; i < num_string_properties; i++) { | 69 for (int i = 0; i < num_string_properties; i++) { |
69 Object* key = string_properties_->KeyAt(string_properties_index); | 70 Object* key = string_properties_->KeyAt(string_properties_index); |
70 result->set(insertion_index, key); | 71 result->set(insertion_index, key); |
71 insertion_index++; | 72 insertion_index++; |
72 string_properties_index++; | 73 string_properties_index++; |
73 } | 74 } |
74 // Add the symbol property keys for this prototype level. | 75 // Add the symbol property keys for this prototype level. |
75 for (int i = 0; i < num_symbol_properties; i++) { | 76 for (int i = 0; i < num_symbol_properties; i++) { |
76 Object* key = symbol_properties_->KeyAt(symbol_properties_index); | 77 Object* key = symbol_properties_->KeyAt(symbol_properties_index); |
77 result->set(insertion_index, key); | 78 result->set(insertion_index, key); |
78 insertion_index++; | 79 insertion_index++; |
79 symbol_properties_index++; | 80 symbol_properties_index++; |
80 } | 81 } |
| 82 if (FLAG_trace_for_in_enumerate) { |
| 83 PrintF("| strings=%d symbols=%d elements=%i ", num_string_properties, |
| 84 num_symbol_properties, num_elements); |
| 85 } |
| 86 } |
| 87 if (FLAG_trace_for_in_enumerate) { |
| 88 PrintF("|| prototypes=%zu ||\n", max_level); |
81 } | 89 } |
82 | 90 |
83 DCHECK_EQ(insertion_index, length_); | 91 DCHECK_EQ(insertion_index, length_); |
84 return result; | 92 return result; |
85 } | 93 } |
86 | 94 |
87 namespace { | 95 namespace { |
88 | 96 |
89 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { | 97 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { |
90 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); | 98 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel && | 359 receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel && |
352 !JSObject::cast(*receiver_)->HasEnumerableElements(); | 360 !JSObject::cast(*receiver_)->HasEnumerableElements(); |
353 } | 361 } |
354 | 362 |
355 namespace { | 363 namespace { |
356 Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, | 364 Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, |
357 Handle<JSObject> object, | 365 Handle<JSObject> object, |
358 GetKeysConversion convert) { | 366 GetKeysConversion convert) { |
359 Handle<FixedArray> keys = JSObject::GetFastEnumPropertyKeys(isolate, object); | 367 Handle<FixedArray> keys = JSObject::GetFastEnumPropertyKeys(isolate, object); |
360 ElementsAccessor* accessor = object->GetElementsAccessor(); | 368 ElementsAccessor* accessor = object->GetElementsAccessor(); |
361 return accessor->PrependElementIndices(object, keys, convert, | 369 Handle<FixedArray> result = |
362 ONLY_ENUMERABLE); | 370 accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE); |
| 371 |
| 372 if (FLAG_trace_for_in_enumerate) { |
| 373 PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n", |
| 374 keys->length(), result->length() - keys->length()); |
| 375 } |
| 376 return result; |
363 } | 377 } |
364 | 378 |
365 MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache( | 379 MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache( |
366 Isolate* isolate, Handle<JSObject> object) { | 380 Isolate* isolate, Handle<JSObject> object) { |
367 // Uninitalized enum cache | 381 // Uninitalized enum cache |
368 Map* map = object->map(); | 382 Map* map = object->map(); |
369 if (object->elements() != isolate->heap()->empty_fixed_array() || | 383 if (object->elements() != isolate->heap()->empty_fixed_array() || |
370 object->elements() != isolate->heap()->empty_slow_element_dictionary()) { | 384 object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
371 // Assume that there are elements. | 385 // Assume that there are elements. |
372 return MaybeHandle<FixedArray>(); | 386 return MaybeHandle<FixedArray>(); |
(...skipping 27 matching lines...) Expand all Loading... |
400 | 414 |
401 Handle<FixedArray> keys; | 415 Handle<FixedArray> keys; |
402 DCHECK(receiver_->IsJSObject()); | 416 DCHECK(receiver_->IsJSObject()); |
403 Handle<JSObject> object = Handle<JSObject>::cast(receiver_); | 417 Handle<JSObject> object = Handle<JSObject>::cast(receiver_); |
404 | 418 |
405 int enum_length = receiver_->map()->EnumLength(); | 419 int enum_length = receiver_->map()->EnumLength(); |
406 if (enum_length == kInvalidEnumCacheSentinel) { | 420 if (enum_length == kInvalidEnumCacheSentinel) { |
407 // Try initializing the enum cache and return own properties. | 421 // Try initializing the enum cache and return own properties. |
408 if (GetOwnKeysWithUninitializedEnumCache(isolate_, object) | 422 if (GetOwnKeysWithUninitializedEnumCache(isolate_, object) |
409 .ToHandle(&keys)) { | 423 .ToHandle(&keys)) { |
| 424 if (FLAG_trace_for_in_enumerate) { |
| 425 PrintF("| strings=%d symbols=0 elements=0 || prototypes>=1 ||\n", |
| 426 keys->length()); |
| 427 } |
| 428 |
410 is_receiver_simple_enum_ = | 429 is_receiver_simple_enum_ = |
411 object->map()->EnumLength() != kInvalidEnumCacheSentinel; | 430 object->map()->EnumLength() != kInvalidEnumCacheSentinel; |
412 return keys; | 431 return keys; |
413 } | 432 } |
414 } | 433 } |
415 // The properties-only case failed because there were probably elements on the | 434 // The properties-only case failed because there were probably elements on the |
416 // receiver. | 435 // receiver. |
417 return GetOwnKeysWithElements(isolate_, object, convert); | 436 return GetOwnKeysWithElements(isolate_, object, convert); |
418 } | 437 } |
419 | 438 |
420 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( | 439 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( |
421 GetKeysConversion convert) { | 440 GetKeysConversion convert) { |
422 return JSReceiver::GetKeys(receiver_, type_, ENUMERABLE_STRINGS); | 441 return JSReceiver::GetKeys(receiver_, type_, ENUMERABLE_STRINGS); |
423 } | 442 } |
424 | 443 |
425 } // namespace internal | 444 } // namespace internal |
426 } // namespace v8 | 445 } // namespace v8 |
OLD | NEW |