OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 // Review notes: | 5 // Review notes: |
6 // | 6 // |
7 // - The use of macros in these inline functions may seem superfluous | 7 // - The use of macros in these inline functions may seem superfluous |
8 // but it is absolutely needed to make sure gcc generates optimal | 8 // but it is absolutely needed to make sure gcc generates optimal |
9 // code. gcc is not happy when attempting to inline too deep. | 9 // code. gcc is not happy when attempting to inline too deep. |
10 // | 10 // |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 } | 165 } |
166 | 166 |
167 bool HeapObject::IsName() const { | 167 bool HeapObject::IsName() const { |
168 return map()->instance_type() <= LAST_NAME_TYPE; | 168 return map()->instance_type() <= LAST_NAME_TYPE; |
169 } | 169 } |
170 | 170 |
171 bool HeapObject::IsUniqueName() const { | 171 bool HeapObject::IsUniqueName() const { |
172 return IsInternalizedString() || IsSymbol(); | 172 return IsInternalizedString() || IsSymbol(); |
173 } | 173 } |
174 | 174 |
| 175 bool Name::IsUniqueName() const { |
| 176 uint32_t type = map()->instance_type(); |
| 177 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) != |
| 178 (kStringTag | kNotInternalizedTag); |
| 179 } |
| 180 |
175 bool HeapObject::IsFunction() const { | 181 bool HeapObject::IsFunction() const { |
176 STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); | 182 STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); |
177 return map()->instance_type() >= FIRST_FUNCTION_TYPE; | 183 return map()->instance_type() >= FIRST_FUNCTION_TYPE; |
178 } | 184 } |
179 | 185 |
180 bool HeapObject::IsCallable() const { return map()->is_callable(); } | 186 bool HeapObject::IsCallable() const { return map()->is_callable(); } |
181 | 187 |
182 bool HeapObject::IsConstructor() const { return map()->is_constructor(); } | 188 bool HeapObject::IsConstructor() const { return map()->is_constructor(); } |
183 | 189 |
184 bool HeapObject::IsTemplateInfo() const { | 190 bool HeapObject::IsTemplateInfo() const { |
(...skipping 2346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2531 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); | 2537 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); |
2532 } | 2538 } |
2533 | 2539 |
2534 | 2540 |
2535 Object** DescriptorArray::GetEnumCacheSlot() { | 2541 Object** DescriptorArray::GetEnumCacheSlot() { |
2536 DCHECK(HasEnumCache()); | 2542 DCHECK(HasEnumCache()); |
2537 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), | 2543 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), |
2538 kEnumCacheOffset); | 2544 kEnumCacheOffset); |
2539 } | 2545 } |
2540 | 2546 |
2541 | 2547 // Perform a binary search in a fixed array. |
2542 // Perform a binary search in a fixed array. Low and high are entry indices. If | |
2543 // there are three entries in this array it should be called with low=0 and | |
2544 // high=2. | |
2545 template <SearchMode search_mode, typename T> | 2548 template <SearchMode search_mode, typename T> |
2546 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries, | 2549 int BinarySearch(T* array, Name* name, int valid_entries, |
2547 int* out_insertion_index) { | 2550 int* out_insertion_index) { |
2548 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL); | 2551 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL); |
2549 uint32_t hash = name->Hash(); | 2552 int low = 0; |
| 2553 int high = array->number_of_entries() - 1; |
| 2554 uint32_t hash = name->hash_field(); |
2550 int limit = high; | 2555 int limit = high; |
2551 | 2556 |
2552 DCHECK(low <= high); | 2557 DCHECK(low <= high); |
2553 | 2558 |
2554 while (low != high) { | 2559 while (low != high) { |
2555 int mid = low + (high - low) / 2; | 2560 int mid = low + (high - low) / 2; |
2556 Name* mid_name = array->GetSortedKey(mid); | 2561 Name* mid_name = array->GetSortedKey(mid); |
2557 uint32_t mid_hash = mid_name->Hash(); | 2562 uint32_t mid_hash = mid_name->hash_field(); |
2558 | 2563 |
2559 if (mid_hash >= hash) { | 2564 if (mid_hash >= hash) { |
2560 high = mid; | 2565 high = mid; |
2561 } else { | 2566 } else { |
2562 low = mid + 1; | 2567 low = mid + 1; |
2563 } | 2568 } |
2564 } | 2569 } |
2565 | 2570 |
2566 for (; low <= limit; ++low) { | 2571 for (; low <= limit; ++low) { |
2567 int sort_index = array->GetSortedKeyIndex(low); | 2572 int sort_index = array->GetSortedKeyIndex(low); |
2568 Name* entry = array->GetKey(sort_index); | 2573 Name* entry = array->GetKey(sort_index); |
2569 uint32_t current_hash = entry->Hash(); | 2574 uint32_t current_hash = entry->hash_field(); |
2570 if (current_hash != hash) { | 2575 if (current_hash != hash) { |
2571 if (out_insertion_index != NULL) { | 2576 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { |
2572 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); | 2577 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); |
2573 } | 2578 } |
2574 return T::kNotFound; | 2579 return T::kNotFound; |
2575 } | 2580 } |
2576 if (entry->Equals(name)) { | 2581 if (entry == name) { |
2577 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) { | 2582 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) { |
2578 return sort_index; | 2583 return sort_index; |
2579 } | 2584 } |
2580 return T::kNotFound; | 2585 return T::kNotFound; |
2581 } | 2586 } |
2582 } | 2587 } |
2583 | 2588 |
2584 if (out_insertion_index != NULL) *out_insertion_index = limit + 1; | 2589 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { |
| 2590 *out_insertion_index = limit + 1; |
| 2591 } |
2585 return T::kNotFound; | 2592 return T::kNotFound; |
2586 } | 2593 } |
2587 | 2594 |
2588 | 2595 |
2589 // Perform a linear search in this fixed array. len is the number of entry | 2596 // Perform a linear search in this fixed array. len is the number of entry |
2590 // indices that are valid. | 2597 // indices that are valid. |
2591 template <SearchMode search_mode, typename T> | 2598 template <SearchMode search_mode, typename T> |
2592 int LinearSearch(T* array, Name* name, int len, int valid_entries, | 2599 int LinearSearch(T* array, Name* name, int valid_entries, |
2593 int* out_insertion_index) { | 2600 int* out_insertion_index) { |
2594 if (search_mode == ALL_ENTRIES) { | 2601 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { |
2595 uint32_t hash = name->Hash(); | 2602 uint32_t hash = name->hash_field(); |
| 2603 int len = array->number_of_entries(); |
2596 for (int number = 0; number < len; number++) { | 2604 for (int number = 0; number < len; number++) { |
2597 int sorted_index = array->GetSortedKeyIndex(number); | 2605 int sorted_index = array->GetSortedKeyIndex(number); |
2598 Name* entry = array->GetKey(sorted_index); | 2606 Name* entry = array->GetKey(sorted_index); |
2599 uint32_t current_hash = entry->Hash(); | 2607 uint32_t current_hash = entry->hash_field(); |
2600 if (current_hash > hash) { | 2608 if (current_hash > hash) { |
2601 if (out_insertion_index != NULL) *out_insertion_index = sorted_index; | 2609 *out_insertion_index = sorted_index; |
2602 return T::kNotFound; | 2610 return T::kNotFound; |
2603 } | 2611 } |
2604 if (current_hash == hash && entry->Equals(name)) return sorted_index; | 2612 if (entry == name) return sorted_index; |
2605 } | 2613 } |
2606 if (out_insertion_index != NULL) *out_insertion_index = len; | 2614 *out_insertion_index = len; |
2607 return T::kNotFound; | 2615 return T::kNotFound; |
2608 } else { | 2616 } else { |
2609 DCHECK(len >= valid_entries); | 2617 DCHECK_LE(valid_entries, array->number_of_entries()); |
2610 DCHECK_NULL(out_insertion_index); // Not supported here. | 2618 DCHECK_NULL(out_insertion_index); // Not supported here. |
2611 for (int number = 0; number < valid_entries; number++) { | 2619 for (int number = 0; number < valid_entries; number++) { |
2612 if (array->GetKey(number)->Equals(name)) return number; | 2620 if (array->GetKey(number) == name) return number; |
2613 } | 2621 } |
2614 return T::kNotFound; | 2622 return T::kNotFound; |
2615 } | 2623 } |
2616 } | 2624 } |
2617 | 2625 |
2618 | 2626 |
2619 template <SearchMode search_mode, typename T> | 2627 template <SearchMode search_mode, typename T> |
2620 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) { | 2628 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) { |
2621 if (search_mode == VALID_ENTRIES) { | 2629 SLOW_DCHECK(array->IsSortedNoDuplicates()); |
2622 SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries)); | |
2623 } else { | |
2624 SLOW_DCHECK(array->IsSortedNoDuplicates()); | |
2625 } | |
2626 | 2630 |
2627 int nof = array->number_of_entries(); | 2631 if (valid_entries == 0) { |
2628 if (nof == 0) { | 2632 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { |
2629 if (out_insertion_index != NULL) *out_insertion_index = 0; | 2633 *out_insertion_index = 0; |
| 2634 } |
2630 return T::kNotFound; | 2635 return T::kNotFound; |
2631 } | 2636 } |
2632 | 2637 |
2633 // Fast case: do linear search for small arrays. | 2638 // Fast case: do linear search for small arrays. |
2634 const int kMaxElementsForLinearSearch = 8; | 2639 const int kMaxElementsForLinearSearch = 8; |
2635 if ((search_mode == ALL_ENTRIES && | 2640 if (valid_entries <= kMaxElementsForLinearSearch) { |
2636 nof <= kMaxElementsForLinearSearch) || | 2641 return LinearSearch<search_mode>(array, name, valid_entries, |
2637 (search_mode == VALID_ENTRIES && | |
2638 valid_entries <= (kMaxElementsForLinearSearch * 3))) { | |
2639 return LinearSearch<search_mode>(array, name, nof, valid_entries, | |
2640 out_insertion_index); | 2642 out_insertion_index); |
2641 } | 2643 } |
2642 | 2644 |
2643 // Slow case: perform binary search. | 2645 // Slow case: perform binary search. |
2644 return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries, | 2646 return BinarySearch<search_mode>(array, name, valid_entries, |
2645 out_insertion_index); | 2647 out_insertion_index); |
2646 } | 2648 } |
2647 | 2649 |
2648 | 2650 |
2649 int DescriptorArray::Search(Name* name, int valid_descriptors) { | 2651 int DescriptorArray::Search(Name* name, int valid_descriptors) { |
| 2652 DCHECK(name->IsUniqueName()); |
2650 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL); | 2653 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL); |
2651 } | 2654 } |
2652 | 2655 |
2653 int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) { | 2656 int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) { |
| 2657 DCHECK(name->IsUniqueName()); |
2654 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 2658 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
2655 if (number_of_own_descriptors == 0) return kNotFound; | 2659 if (number_of_own_descriptors == 0) return kNotFound; |
2656 | 2660 |
2657 DescriptorLookupCache* cache = isolate->descriptor_lookup_cache(); | 2661 DescriptorLookupCache* cache = isolate->descriptor_lookup_cache(); |
2658 int number = cache->Lookup(map, name); | 2662 int number = cache->Lookup(map, name); |
2659 | 2663 |
2660 if (number == DescriptorLookupCache::kAbsent) { | 2664 if (number == DescriptorLookupCache::kAbsent) { |
2661 number = Search(name, number_of_own_descriptors); | 2665 number = Search(name, number_of_own_descriptors); |
2662 cache->Update(map, name, number); | 2666 cache->Update(map, name, number); |
2663 } | 2667 } |
2664 | 2668 |
2665 return number; | 2669 return number; |
2666 } | 2670 } |
2667 | 2671 |
2668 | |
2669 PropertyDetails Map::GetLastDescriptorDetails() { | 2672 PropertyDetails Map::GetLastDescriptorDetails() { |
2670 return instance_descriptors()->GetDetails(LastAdded()); | 2673 return instance_descriptors()->GetDetails(LastAdded()); |
2671 } | 2674 } |
2672 | 2675 |
2673 | 2676 |
2674 int Map::LastAdded() { | 2677 int Map::LastAdded() { |
2675 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 2678 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
2676 DCHECK(number_of_own_descriptors > 0); | 2679 DCHECK(number_of_own_descriptors > 0); |
2677 return number_of_own_descriptors - 1; | 2680 return number_of_own_descriptors - 1; |
2678 } | 2681 } |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3415 | 3418 |
3416 | 3419 |
3417 Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) { | 3420 Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) { |
3418 if (!string->IsConsString()) return string; | 3421 if (!string->IsConsString()) return string; |
3419 Handle<ConsString> cons = Handle<ConsString>::cast(string); | 3422 Handle<ConsString> cons = Handle<ConsString>::cast(string); |
3420 if (cons->IsFlat()) return handle(cons->first()); | 3423 if (cons->IsFlat()) return handle(cons->first()); |
3421 return SlowFlatten(cons, pretenure); | 3424 return SlowFlatten(cons, pretenure); |
3422 } | 3425 } |
3423 | 3426 |
3424 | 3427 |
3425 Handle<Name> Name::Flatten(Handle<Name> name, PretenureFlag pretenure) { | |
3426 if (name->IsSymbol()) return name; | |
3427 return String::Flatten(Handle<String>::cast(name)); | |
3428 } | |
3429 | |
3430 | |
3431 uint16_t String::Get(int index) { | 3428 uint16_t String::Get(int index) { |
3432 DCHECK(index >= 0 && index < length()); | 3429 DCHECK(index >= 0 && index < length()); |
3433 switch (StringShape(this).full_representation_tag()) { | 3430 switch (StringShape(this).full_representation_tag()) { |
3434 case kSeqStringTag | kOneByteStringTag: | 3431 case kSeqStringTag | kOneByteStringTag: |
3435 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index); | 3432 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index); |
3436 case kSeqStringTag | kTwoByteStringTag: | 3433 case kSeqStringTag | kTwoByteStringTag: |
3437 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); | 3434 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); |
3438 case kConsStringTag | kOneByteStringTag: | 3435 case kConsStringTag | kOneByteStringTag: |
3439 case kConsStringTag | kTwoByteStringTag: | 3436 case kConsStringTag | kTwoByteStringTag: |
3440 return ConsString::cast(this)->ConsStringGet(index); | 3437 return ConsString::cast(this)->ConsStringGet(index); |
(...skipping 4231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7672 #undef WRITE_INT64_FIELD | 7669 #undef WRITE_INT64_FIELD |
7673 #undef READ_BYTE_FIELD | 7670 #undef READ_BYTE_FIELD |
7674 #undef WRITE_BYTE_FIELD | 7671 #undef WRITE_BYTE_FIELD |
7675 #undef NOBARRIER_READ_BYTE_FIELD | 7672 #undef NOBARRIER_READ_BYTE_FIELD |
7676 #undef NOBARRIER_WRITE_BYTE_FIELD | 7673 #undef NOBARRIER_WRITE_BYTE_FIELD |
7677 | 7674 |
7678 } // namespace internal | 7675 } // namespace internal |
7679 } // namespace v8 | 7676 } // namespace v8 |
7680 | 7677 |
7681 #endif // V8_OBJECTS_INL_H_ | 7678 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |