| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 9515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9526 | 9526 |
| 9527 | 9527 |
| 9528 void String::PrintOn(FILE* file) { | 9528 void String::PrintOn(FILE* file) { |
| 9529 int length = this->length(); | 9529 int length = this->length(); |
| 9530 for (int i = 0; i < length; i++) { | 9530 for (int i = 0; i < length; i++) { |
| 9531 PrintF(file, "%c", Get(i)); | 9531 PrintF(file, "%c", Get(i)); |
| 9532 } | 9532 } |
| 9533 } | 9533 } |
| 9534 | 9534 |
| 9535 | 9535 |
| 9536 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) { | |
| 9537 int live_enum = map->EnumLength(); | |
| 9538 if (live_enum == kInvalidEnumCacheSentinel) { | |
| 9539 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); | |
| 9540 } | |
| 9541 if (live_enum == 0) return descriptors->ClearEnumCache(); | |
| 9542 | |
| 9543 FixedArray* enum_cache = descriptors->GetEnumCache(); | |
| 9544 | |
| 9545 int to_trim = enum_cache->length() - live_enum; | |
| 9546 if (to_trim <= 0) return; | |
| 9547 heap->RightTrimFixedArray<Heap::FROM_GC>( | |
| 9548 descriptors->GetEnumCache(), to_trim); | |
| 9549 | |
| 9550 if (!descriptors->HasEnumIndicesCache()) return; | |
| 9551 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); | |
| 9552 heap->RightTrimFixedArray<Heap::FROM_GC>(enum_indices_cache, to_trim); | |
| 9553 } | |
| 9554 | |
| 9555 | |
| 9556 static void TrimDescriptorArray(Heap* heap, | |
| 9557 Map* map, | |
| 9558 DescriptorArray* descriptors, | |
| 9559 int number_of_own_descriptors) { | |
| 9560 int number_of_descriptors = descriptors->number_of_descriptors_storage(); | |
| 9561 int to_trim = number_of_descriptors - number_of_own_descriptors; | |
| 9562 if (to_trim == 0) return; | |
| 9563 | |
| 9564 heap->RightTrimFixedArray<Heap::FROM_GC>( | |
| 9565 descriptors, to_trim * DescriptorArray::kDescriptorSize); | |
| 9566 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | |
| 9567 | |
| 9568 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); | |
| 9569 descriptors->Sort(); | |
| 9570 } | |
| 9571 | |
| 9572 | |
| 9573 // Clear a possible back pointer in case the transition leads to a dead map. | |
| 9574 // Return true in case a back pointer has been cleared and false otherwise. | |
| 9575 static bool ClearBackPointer(Heap* heap, Map* target) { | |
| 9576 if (Marking::MarkBitFrom(target).Get()) return false; | |
| 9577 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | |
| 9578 return true; | |
| 9579 } | |
| 9580 | |
| 9581 | |
| 9582 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, | |
| 9583 // because it cannot be called from outside the GC and we already have methods | |
| 9584 // depending on the transitions layout in the GC anyways. | |
| 9585 void Map::ClearNonLiveTransitions(Heap* heap) { | |
| 9586 // If there are no transitions to be cleared, return. | |
| 9587 // TODO(verwaest) Should be an assert, otherwise back pointers are not | |
| 9588 // properly cleared. | |
| 9589 if (!HasTransitionArray()) return; | |
| 9590 | |
| 9591 TransitionArray* t = transitions(); | |
| 9592 MarkCompactCollector* collector = heap->mark_compact_collector(); | |
| 9593 | |
| 9594 int transition_index = 0; | |
| 9595 | |
| 9596 DescriptorArray* descriptors = instance_descriptors(); | |
| 9597 bool descriptors_owner_died = false; | |
| 9598 | |
| 9599 // Compact all live descriptors to the left. | |
| 9600 for (int i = 0; i < t->number_of_transitions(); ++i) { | |
| 9601 Map* target = t->GetTarget(i); | |
| 9602 if (ClearBackPointer(heap, target)) { | |
| 9603 if (target->instance_descriptors() == descriptors) { | |
| 9604 descriptors_owner_died = true; | |
| 9605 } | |
| 9606 } else { | |
| 9607 if (i != transition_index) { | |
| 9608 Name* key = t->GetKey(i); | |
| 9609 t->SetKey(transition_index, key); | |
| 9610 Object** key_slot = t->GetKeySlot(transition_index); | |
| 9611 collector->RecordSlot(key_slot, key_slot, key); | |
| 9612 // Target slots do not need to be recorded since maps are not compacted. | |
| 9613 t->SetTarget(transition_index, t->GetTarget(i)); | |
| 9614 } | |
| 9615 transition_index++; | |
| 9616 } | |
| 9617 } | |
| 9618 | |
| 9619 // If there are no transitions to be cleared, return. | |
| 9620 // TODO(verwaest) Should be an assert, otherwise back pointers are not | |
| 9621 // properly cleared. | |
| 9622 if (transition_index == t->number_of_transitions()) return; | |
| 9623 | |
| 9624 int number_of_own_descriptors = NumberOfOwnDescriptors(); | |
| 9625 | |
| 9626 if (descriptors_owner_died) { | |
| 9627 if (number_of_own_descriptors > 0) { | |
| 9628 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | |
| 9629 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); | |
| 9630 set_owns_descriptors(true); | |
| 9631 } else { | |
| 9632 DCHECK(descriptors == GetHeap()->empty_descriptor_array()); | |
| 9633 } | |
| 9634 } | |
| 9635 | |
| 9636 // Note that we never eliminate a transition array, though we might right-trim | |
| 9637 // such that number_of_transitions() == 0. If this assumption changes, | |
| 9638 // TransitionArray::CopyInsert() will need to deal with the case that a | |
| 9639 // transition array disappeared during GC. | |
| 9640 int trim = t->number_of_transitions() - transition_index; | |
| 9641 if (trim > 0) { | |
| 9642 heap->RightTrimFixedArray<Heap::FROM_GC>(t, t->IsSimpleTransition() | |
| 9643 ? trim : trim * TransitionArray::kTransitionSize); | |
| 9644 } | |
| 9645 DCHECK(HasTransitionArray()); | |
| 9646 } | |
| 9647 | |
| 9648 | |
| 9649 int Map::Hash() { | 9536 int Map::Hash() { |
| 9650 // For performance reasons we only hash the 3 most variable fields of a map: | 9537 // For performance reasons we only hash the 3 most variable fields of a map: |
| 9651 // constructor, prototype and bit_field2. | 9538 // constructor, prototype and bit_field2. |
| 9652 | 9539 |
| 9653 // Shift away the tag. | 9540 // Shift away the tag. |
| 9654 int hash = (static_cast<uint32_t>( | 9541 int hash = (static_cast<uint32_t>( |
| 9655 reinterpret_cast<uintptr_t>(constructor())) >> 2); | 9542 reinterpret_cast<uintptr_t>(constructor())) >> 2); |
| 9656 | 9543 |
| 9657 // XOR-ing the prototype and constructor directly yields too many zero bits | 9544 // XOR-ing the prototype and constructor directly yields too many zero bits |
| 9658 // when the two pointers are close (which is fairly common). | 9545 // when the two pointers are close (which is fairly common). |
| (...skipping 7344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17003 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16890 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17004 static const char* error_messages_[] = { | 16891 static const char* error_messages_[] = { |
| 17005 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16892 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17006 }; | 16893 }; |
| 17007 #undef ERROR_MESSAGES_TEXTS | 16894 #undef ERROR_MESSAGES_TEXTS |
| 17008 return error_messages_[reason]; | 16895 return error_messages_[reason]; |
| 17009 } | 16896 } |
| 17010 | 16897 |
| 17011 | 16898 |
| 17012 } } // namespace v8::internal | 16899 } } // namespace v8::internal |
| OLD | NEW |