| Index: src/objects-inl.h
|
| diff --git a/src/objects-inl.h b/src/objects-inl.h
|
| index fb3fe647f1a8be00eb543a54dfe8aecd69299fa6..3b9bb0a13783fd6829bbffe3a678b6babeeb08c4 100644
|
| --- a/src/objects-inl.h
|
| +++ b/src/objects-inl.h
|
| @@ -382,9 +382,6 @@ uint32_t StringShape::full_representation_tag() {
|
| STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
|
| Internals::kFullStringRepresentationMask);
|
|
|
| -STATIC_CHECK(static_cast<uint32_t>(kStringEncodingMask) ==
|
| - Internals::kStringEncodingMask);
|
| -
|
|
|
| bool StringShape::IsSequentialAscii() {
|
| return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
|
| @@ -401,12 +398,6 @@ bool StringShape::IsExternalAscii() {
|
| }
|
|
|
|
|
| -STATIC_CHECK((kExternalStringTag | kAsciiStringTag) ==
|
| - Internals::kExternalAsciiRepresentationTag);
|
| -
|
| -STATIC_CHECK(v8::String::ASCII_ENCODING == kAsciiStringTag);
|
| -
|
| -
|
| bool StringShape::IsExternalTwoByte() {
|
| return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
|
| }
|
| @@ -415,7 +406,6 @@ bool StringShape::IsExternalTwoByte() {
|
| STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
|
| Internals::kExternalTwoByteRepresentationTag);
|
|
|
| -STATIC_CHECK(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
|
|
|
| uc32 FlatStringReader::Get(int index) {
|
| ASSERT(0 <= index && index <= length_);
|
| @@ -1906,12 +1896,6 @@ bool DescriptorArray::IsEmpty() {
|
| }
|
|
|
|
|
| -void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
|
| - WRITE_FIELD(
|
| - this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
|
| -}
|
| -
|
| -
|
| // Perform a binary search in a fixed array. Low and high are entry indices. If
|
| // there are three entries in this array it should be called with low=0 and
|
| // high=2.
|
| @@ -1946,45 +1930,31 @@ int BinarySearch(T* array, String* name, int low, int high) {
|
|
|
| // Perform a linear search in this fixed array. len is the number of entry
|
| // indices that are valid.
|
| -template<SearchMode search_mode, typename T>
|
| -int LinearSearch(T* array, String* name, int len, int valid_entries) {
|
| +template<typename T>
|
| +int LinearSearch(T* array, String* name, int len) {
|
| uint32_t hash = name->Hash();
|
| - if (search_mode == ALL_ENTRIES) {
|
| - for (int number = 0; number < len; number++) {
|
| - int sorted_index = array->GetSortedKeyIndex(number);
|
| - String* entry = array->GetKey(sorted_index);
|
| - uint32_t current_hash = entry->Hash();
|
| - if (current_hash > hash) break;
|
| - if (current_hash == hash && entry->Equals(name)) return sorted_index;
|
| - }
|
| - } else {
|
| - ASSERT(len >= valid_entries);
|
| - for (int number = 0; number < valid_entries; number++) {
|
| - String* entry = array->GetKey(number);
|
| - uint32_t current_hash = entry->Hash();
|
| - if (current_hash == hash && entry->Equals(name)) return number;
|
| - }
|
| + for (int number = 0; number < len; number++) {
|
| + int sorted_index = array->GetSortedKeyIndex(number);
|
| + String* entry = array->GetKey(sorted_index);
|
| + uint32_t current_hash = entry->Hash();
|
| + if (current_hash > hash) break;
|
| + if (current_hash == hash && entry->Equals(name)) return sorted_index;
|
| }
|
| return T::kNotFound;
|
| }
|
|
|
|
|
| -template<SearchMode search_mode, typename T>
|
| -int Search(T* array, String* name, int valid_entries) {
|
| - if (search_mode == VALID_ENTRIES) {
|
| - SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
|
| - } else {
|
| - SLOW_ASSERT(array->IsSortedNoDuplicates());
|
| - }
|
| +template<typename T>
|
| +int Search(T* array, String* name) {
|
| + SLOW_ASSERT(array->IsSortedNoDuplicates());
|
|
|
| int nof = array->number_of_entries();
|
| if (nof == 0) return T::kNotFound;
|
|
|
| // Fast case: do linear search for small arrays.
|
| const int kMaxElementsForLinearSearch = 8;
|
| - if (search_mode == VALID_ENTRIES ||
|
| - (search_mode == ALL_ENTRIES && nof < kMaxElementsForLinearSearch)) {
|
| - return LinearSearch<search_mode>(array, name, nof, valid_entries);
|
| + if (nof < kMaxElementsForLinearSearch) {
|
| + return LinearSearch(array, name, nof);
|
| }
|
|
|
| // Slow case: perform binary search.
|
| @@ -1992,21 +1962,20 @@ int Search(T* array, String* name, int valid_entries) {
|
| }
|
|
|
|
|
| -int DescriptorArray::Search(String* name, int valid_descriptors) {
|
| - return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
|
| +int DescriptorArray::Search(String* name) {
|
| + return internal::Search(this, name);
|
| }
|
|
|
|
|
| -int DescriptorArray::SearchWithCache(String* name, Map* map) {
|
| - int number_of_own_descriptors = map->NumberOfOwnDescriptors();
|
| - if (number_of_own_descriptors == 0) return kNotFound;
|
| +int DescriptorArray::SearchWithCache(String* name) {
|
| + if (number_of_descriptors() == 0) return kNotFound;
|
|
|
| DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
|
| - int number = cache->Lookup(map, name);
|
| + int number = cache->Lookup(this, name);
|
|
|
| if (number == DescriptorLookupCache::kAbsent) {
|
| - number = Search(name, number_of_own_descriptors);
|
| - cache->Update(map, name, number);
|
| + number = Search(name);
|
| + cache->Update(this, name, number);
|
| }
|
|
|
| return number;
|
| @@ -2017,7 +1986,7 @@ void Map::LookupDescriptor(JSObject* holder,
|
| String* name,
|
| LookupResult* result) {
|
| DescriptorArray* descriptors = this->instance_descriptors();
|
| - int number = descriptors->SearchWithCache(name, this);
|
| + int number = descriptors->SearchWithCache(name);
|
| if (number == DescriptorArray::kNotFound) return result->NotFound();
|
| result->DescriptorResult(holder, descriptors->GetDetails(number), number);
|
| }
|
| @@ -2061,9 +2030,10 @@ String* DescriptorArray::GetSortedKey(int descriptor_number) {
|
| }
|
|
|
|
|
| -void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
|
| - PropertyDetails details = GetDetails(descriptor_index);
|
| - set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
|
| +void DescriptorArray::SetSortedKey(int pointer, int descriptor_number) {
|
| + int details_index = ToDetailsIndex(pointer);
|
| + PropertyDetails details = PropertyDetails(Smi::cast(get(details_index)));
|
| + set_unchecked(details_index, details.set_pointer(descriptor_number).AsSmi());
|
| }
|
|
|
|
|
| @@ -2144,65 +2114,24 @@ void DescriptorArray::Set(int descriptor_number,
|
| }
|
|
|
|
|
| -void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
|
| - // Range check.
|
| - ASSERT(descriptor_number < number_of_descriptors());
|
| - ASSERT(desc->GetDetails().descriptor_index() <=
|
| - number_of_descriptors());
|
| - ASSERT(desc->GetDetails().descriptor_index() > 0);
|
| -
|
| - set(ToKeyIndex(descriptor_number), desc->GetKey());
|
| - set(ToValueIndex(descriptor_number), desc->GetValue());
|
| - set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
|
| -}
|
| -
|
| -
|
| -void DescriptorArray::EraseDescriptor(Heap* heap, int descriptor_number) {
|
| - set_null_unchecked(heap, ToKeyIndex(descriptor_number));
|
| - set_null_unchecked(heap, ToValueIndex(descriptor_number));
|
| -}
|
| -
|
| -
|
| void DescriptorArray::Append(Descriptor* desc,
|
| - const WhitenessWitness& witness) {
|
| - int descriptor_number = number_of_descriptors();
|
| - int enumeration_index = descriptor_number + 1;
|
| - SetNumberOfDescriptors(descriptor_number + 1);
|
| - desc->SetEnumerationIndex(enumeration_index);
|
| - Set(descriptor_number, desc, witness);
|
| -
|
| - uint32_t hash = desc->GetKey()->Hash();
|
| -
|
| - int insertion;
|
| -
|
| - for (insertion = descriptor_number; insertion > 0; --insertion) {
|
| - String* key = GetSortedKey(insertion - 1);
|
| - if (key->Hash() <= hash) break;
|
| - SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
|
| - }
|
| -
|
| - SetSortedKey(insertion, descriptor_number);
|
| -}
|
| -
|
| -
|
| -void DescriptorArray::Append(Descriptor* desc) {
|
| - int descriptor_number = number_of_descriptors();
|
| - int enumeration_index = descriptor_number + 1;
|
| - SetNumberOfDescriptors(descriptor_number + 1);
|
| + const WhitenessWitness& witness,
|
| + int number_of_set_descriptors) {
|
| + int enumeration_index = number_of_set_descriptors + 1;
|
| desc->SetEnumerationIndex(enumeration_index);
|
| - Set(descriptor_number, desc);
|
| + Set(number_of_set_descriptors, desc, witness);
|
|
|
| uint32_t hash = desc->GetKey()->Hash();
|
|
|
| int insertion;
|
|
|
| - for (insertion = descriptor_number; insertion > 0; --insertion) {
|
| + for (insertion = number_of_set_descriptors; insertion > 0; --insertion) {
|
| String* key = GetSortedKey(insertion - 1);
|
| if (key->Hash() <= hash) break;
|
| SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
|
| }
|
|
|
| - SetSortedKey(insertion, descriptor_number);
|
| + SetSortedKey(insertion, number_of_set_descriptors);
|
| }
|
|
|
|
|
| @@ -2213,14 +2142,14 @@ void DescriptorArray::SwapSortedKeys(int first, int second) {
|
| }
|
|
|
|
|
| -DescriptorArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
|
| +FixedArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
|
| : marking_(array->GetHeap()->incremental_marking()) {
|
| marking_->EnterNoMarkingScope();
|
| ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
|
| }
|
|
|
|
|
| -DescriptorArray::WhitenessWitness::~WhitenessWitness() {
|
| +FixedArray::WhitenessWitness::~WhitenessWitness() {
|
| marking_->LeaveNoMarkingScope();
|
| }
|
|
|
| @@ -3101,16 +3030,6 @@ Code::Flags Code::flags() {
|
| }
|
|
|
|
|
| -void Map::set_owns_descriptors(bool is_shared) {
|
| - set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
|
| -}
|
| -
|
| -
|
| -bool Map::owns_descriptors() {
|
| - return OwnsDescriptors::decode(bit_field3());
|
| -}
|
| -
|
| -
|
| void Code::set_flags(Code::Flags flags) {
|
| STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
|
| // Make sure that all call stubs have an arguments count.
|
| @@ -3546,66 +3465,41 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
|
| }
|
|
|
|
|
| -JSGlobalPropertyCell* Map::descriptors_pointer() {
|
| - ASSERT(HasTransitionArray());
|
| - return transitions()->descriptors_pointer();
|
| -}
|
| -
|
| -
|
| DescriptorArray* Map::instance_descriptors() {
|
| - if (HasTransitionArray()) return transitions()->descriptors();
|
| - Object* back_pointer = GetBackPointer();
|
| - if (!back_pointer->IsMap()) return GetHeap()->empty_descriptor_array();
|
| - return Map::cast(back_pointer)->instance_descriptors();
|
| + if (!HasTransitionArray()) return GetHeap()->empty_descriptor_array();
|
| + return transitions()->descriptors();
|
| }
|
|
|
|
|
| -enum TransitionsKind { DESCRIPTORS_HOLDER, FULL_TRANSITION_ARRAY };
|
| -
|
| -
|
| // If the descriptor is using the empty transition array, install a new empty
|
| // transition array that will have place for an element transition.
|
| -static MaybeObject* EnsureHasTransitionArray(Map* map, TransitionsKind kind) {
|
| +static MaybeObject* EnsureHasTransitionArray(Map* map) {
|
| + if (map->HasTransitionArray()) return map;
|
| +
|
| TransitionArray* transitions;
|
| - MaybeObject* maybe_transitions;
|
| - if (map->HasTransitionArray()) {
|
| - if (kind != FULL_TRANSITION_ARRAY ||
|
| - map->transitions()->IsFullTransitionArray()) {
|
| - return map;
|
| - }
|
| - maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
|
| - if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
| - } else {
|
| - JSGlobalPropertyCell* pointer = map->RetrieveDescriptorsPointer();
|
| - if (kind == FULL_TRANSITION_ARRAY) {
|
| - maybe_transitions = TransitionArray::Allocate(0, pointer);
|
| - } else {
|
| - maybe_transitions = TransitionArray::AllocateDescriptorsHolder(pointer);
|
| - }
|
| - if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
| - transitions->set_back_pointer_storage(map->GetBackPointer());
|
| - }
|
| + MaybeObject* maybe_transitions = TransitionArray::Allocate(0);
|
| + if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
| map->set_transitions(transitions);
|
| return transitions;
|
| }
|
|
|
|
|
| -MaybeObject* Map::SetDescriptors(DescriptorArray* value) {
|
| +MaybeObject* Map::SetDescriptors(DescriptorArray* value,
|
| + WriteBarrierMode mode) {
|
| ASSERT(!is_shared());
|
| - MaybeObject* maybe_failure =
|
| - EnsureHasTransitionArray(this, DESCRIPTORS_HOLDER);
|
| + MaybeObject* maybe_failure = EnsureHasTransitionArray(this);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|
| - ASSERT(NumberOfOwnDescriptors() <= value->number_of_descriptors());
|
| - transitions()->set_descriptors(value);
|
| + transitions()->set_descriptors(value, mode);
|
| return this;
|
| }
|
|
|
|
|
| MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
|
| - int len = descriptors->number_of_descriptors();
|
| #ifdef DEBUG
|
| + int len = descriptors->number_of_descriptors();
|
| ASSERT(len <= DescriptorArray::kMaxNumberOfDescriptors);
|
| + SLOW_ASSERT(descriptors->IsSortedNoDuplicates());
|
|
|
| bool used_indices[DescriptorArray::kMaxNumberOfDescriptors];
|
| for (int i = 0; i < len; ++i) used_indices[i] = false;
|
| @@ -3624,7 +3518,8 @@ MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
|
| MaybeObject* maybe_failure = SetDescriptors(descriptors);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|
| - SetNumberOfOwnDescriptors(len);
|
| + SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
|
| +
|
| return this;
|
| }
|
|
|
| @@ -3652,8 +3547,8 @@ void Map::AppendDescriptor(Descriptor* desc,
|
| const DescriptorArray::WhitenessWitness& witness) {
|
| DescriptorArray* descriptors = instance_descriptors();
|
| int number_of_own_descriptors = NumberOfOwnDescriptors();
|
| - ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
|
| - descriptors->Append(desc, witness);
|
| + ASSERT(number_of_own_descriptors < descriptors->number_of_descriptors());
|
| + descriptors->Append(desc, witness, number_of_own_descriptors);
|
| SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
|
| }
|
|
|
| @@ -3693,23 +3588,9 @@ bool Map::CanHaveMoreTransitions() {
|
| }
|
|
|
|
|
| -JSGlobalPropertyCell* Map::RetrieveDescriptorsPointer() {
|
| - if (!owns_descriptors()) return NULL;
|
| - Object* back_pointer = GetBackPointer();
|
| - if (back_pointer->IsUndefined()) return NULL;
|
| - Map* map = Map::cast(back_pointer);
|
| - ASSERT(map->HasTransitionArray());
|
| - return map->transitions()->descriptors_pointer();
|
| -}
|
| -
|
| -
|
| -MaybeObject* Map::AddTransition(String* key,
|
| - Map* target,
|
| - SimpleTransitionFlag flag) {
|
| +MaybeObject* Map::AddTransition(String* key, Map* target) {
|
| if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
|
| - JSGlobalPropertyCell* descriptors_pointer = RetrieveDescriptorsPointer();
|
| - return TransitionArray::NewWith(
|
| - flag, key, target, descriptors_pointer, GetBackPointer());
|
| + return TransitionArray::NewWith(key, target);
|
| }
|
|
|
|
|
| @@ -3718,14 +3599,8 @@ void Map::SetTransition(int transition_index, Map* target) {
|
| }
|
|
|
|
|
| -Map* Map::GetTransition(int transition_index) {
|
| - return transitions()->GetTarget(transition_index);
|
| -}
|
| -
|
| -
|
| MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
|
| - MaybeObject* allow_elements =
|
| - EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY);
|
| + MaybeObject* allow_elements = EnsureHasTransitionArray(this);
|
| if (allow_elements->IsFailure()) return allow_elements;
|
| transitions()->set_elements_transition(transitioned_map);
|
| return this;
|
| @@ -3742,8 +3617,7 @@ FixedArray* Map::GetPrototypeTransitions() {
|
|
|
|
|
| MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
|
| - MaybeObject* allow_prototype =
|
| - EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY);
|
| + MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
|
| if (allow_prototype->IsFailure()) return allow_prototype;
|
| #ifdef DEBUG
|
| if (HasPrototypeTransitions()) {
|
| @@ -3770,6 +3644,8 @@ TransitionArray* Map::transitions() {
|
|
|
| void Map::set_transitions(TransitionArray* transition_array,
|
| WriteBarrierMode mode) {
|
| + transition_array->set_descriptors(instance_descriptors());
|
| + transition_array->set_back_pointer_storage(GetBackPointer());
|
| #ifdef DEBUG
|
| if (HasTransitionArray()) {
|
| ASSERT(transitions() != transition_array);
|
| @@ -4949,7 +4825,8 @@ StringHasher::StringHasher(int length, uint32_t seed)
|
| raw_running_hash_(seed),
|
| array_index_(0),
|
| is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
|
| - is_first_char_(true) {
|
| + is_first_char_(true),
|
| + is_valid_(true) {
|
| ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
|
| }
|
|
|
| @@ -4959,25 +4836,6 @@ bool StringHasher::has_trivial_hash() {
|
| }
|
|
|
|
|
| -uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint32_t c) {
|
| - running_hash += c;
|
| - running_hash += (running_hash << 10);
|
| - running_hash ^= (running_hash >> 6);
|
| - return running_hash;
|
| -}
|
| -
|
| -
|
| -uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
|
| - running_hash += (running_hash << 3);
|
| - running_hash ^= (running_hash >> 11);
|
| - running_hash += (running_hash << 15);
|
| - if ((running_hash & String::kHashBitMask) == 0) {
|
| - return 27;
|
| - }
|
| - return running_hash;
|
| -}
|
| -
|
| -
|
| void StringHasher::AddCharacter(uint32_t c) {
|
| if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
|
| AddSurrogatePair(c); // Not inlined.
|
| @@ -4985,7 +4843,9 @@ void StringHasher::AddCharacter(uint32_t c) {
|
| }
|
| // Use the Jenkins one-at-a-time hash function to update the hash
|
| // for the given character.
|
| - raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
|
| + raw_running_hash_ += c;
|
| + raw_running_hash_ += (raw_running_hash_ << 10);
|
| + raw_running_hash_ ^= (raw_running_hash_ >> 6);
|
| // Incremental array index computation.
|
| if (is_array_index_) {
|
| if (c < '0' || c > '9') {
|
| @@ -5015,14 +4875,23 @@ void StringHasher::AddCharacterNoIndex(uint32_t c) {
|
| AddSurrogatePairNoIndex(c); // Not inlined.
|
| return;
|
| }
|
| - raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
|
| + raw_running_hash_ += c;
|
| + raw_running_hash_ += (raw_running_hash_ << 10);
|
| + raw_running_hash_ ^= (raw_running_hash_ >> 6);
|
| }
|
|
|
|
|
| uint32_t StringHasher::GetHash() {
|
| // Get the calculated raw hash value and do some more bit ops to distribute
|
| // the hash further. Ensure that we never return zero as the hash value.
|
| - return GetHashCore(raw_running_hash_);
|
| + uint32_t result = raw_running_hash_;
|
| + result += (result << 3);
|
| + result ^= (result >> 11);
|
| + result += (result << 15);
|
| + if ((result & String::kHashBitMask) == 0) {
|
| + result = 27;
|
| + }
|
| + return result;
|
| }
|
|
|
|
|
|
|