| 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 |