 Chromium Code Reviews
 Chromium Code Reviews Issue 1316213008:
  Speedup JSReceiver::GetKeys  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1316213008:
  Speedup JSReceiver::GetKeys  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/objects.cc | 
| diff --git a/src/objects.cc b/src/objects.cc | 
| index c91ed7c5fd366c24c544b2e4a70637a56e8eabfc..3482271f8170ee50bc4b0bfec4ff0753362133ee 100644 | 
| --- a/src/objects.cc | 
| +++ b/src/objects.cc | 
| @@ -7915,25 +7915,27 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | 
| return result; | 
| } | 
| +namespace { | 
| + | 
| +inline MaybeHandle<FixedArray> LinearUnionOfKeys(Isolate* isolate, | 
| + Handle<FixedArray> first, | 
| + Handle<FixedArray> second) { | 
| + int second_length = second->length(); | 
| + int first_length = first->length(); | 
| -MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, | 
| - Handle<FixedArray> second) { | 
| - if (second->length() == 0) return first; | 
| - if (first->length() == 0) return second; | 
| - Isolate* isolate = first->GetIsolate(); | 
| Handle<FixedArray> result = | 
| - isolate->factory()->NewFixedArray(first->length() + second->length()); | 
| - for (int i = 0; i < first->length(); i++) { | 
| + isolate->factory()->NewFixedArray(first_length + second_length); | 
| + for (int i = 0; i < first_length; i++) { | 
| result->set(i, first->get(i)); | 
| } | 
| - int pos = first->length(); | 
| - for (int j = 0; j < second->length(); j++) { | 
| + int pos = first_length; | 
| + for (int j = 0; j < second_length; j++) { | 
| Object* current = second->get(j); | 
| int i; | 
| - for (i = 0; i < first->length(); i++) { | 
| + for (i = 0; i < first_length; i++) { | 
| if (current->KeyEquals(first->get(i))) break; | 
| } | 
| - if (i == first->length()) { | 
| + if (i == first_length) { | 
| result->set(pos++, current); | 
| } | 
| } | 
| @@ -7942,6 +7944,48 @@ MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, | 
| return result; | 
| } | 
| +inline MaybeHandle<FixedArray> SublinearUnionOfKeys(Isolate* isolate, | 
| + Handle<FixedArray> first, | 
| + Handle<FixedArray> second) { | 
| + int second_length = second->length(); | 
| + int first_length = first->length(); | 
| + | 
| + Handle<FixedArray> result = | 
| + isolate->factory()->NewFixedArray(first_length + second_length); | 
| + Handle<ObjectHashTable> cache = ObjectHashTable::New(isolate, first_length); | 
| + | 
| + for (int i = 0; i < first_length; i++) { | 
| + Handle<Object> value(first->get(i), isolate); | 
| + result->set(i, *value); | 
| + ObjectHashTable::Put(isolate, cache, value, value); | 
| + } | 
| + int pos = first_length; | 
| + for (int i = 0; i < second_length; i++) { | 
| + Handle<Object> current(second->get(i), isolate); | 
| + if (cache->HasKey(isolate, current)) { | 
| + result->set(pos++, *current); | 
| + } | 
| + } | 
| + | 
| + result->Shrink(pos); | 
| + return result; | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| +MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, | 
| + Handle<FixedArray> second) { | 
| + int second_length = second->length(); | 
| + if (second_length == 0) return first; | 
| + int first_length = first->length(); | 
| + if (first_length == 0) return second; | 
| + Isolate* isolate = first->GetIsolate(); | 
| + if (first_length <= 2) { | 
| + return LinearUnionOfKeys(isolate, first, second); | 
| + } | 
| + return SublinearUnionOfKeys(isolate, first, second); | 
| +} | 
| + | 
| void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { | 
| DisallowHeapAllocation no_gc; | 
| @@ -15070,6 +15114,18 @@ Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { | 
| } | 
| +bool ObjectHashTable::HasKey(Isolate* isolate, Handle<Object> key) { | 
| + DisallowHeapAllocation no_gc; | 
| + DCHECK(IsKey(*key)); | 
| + | 
| + // If the object does not have an identity hash, it was never used as a key. | 
| + Object* hash = key->GetHash(); | 
| + if (hash->IsUndefined()) return false; | 
| + int entry = FindEntry(isolate, key, Smi::cast(hash)->value()); | 
| + return entry != kNotFound; | 
| +} | 
| + | 
| + | 
| Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 
| Handle<Object> key, | 
| Handle<Object> value) { | 
| @@ -15108,6 +15164,43 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 
| } | 
| +Handle<ObjectHashTable> ObjectHashTable::Put(Isolate* isolate, | 
| 
Camillo Bruni
2015/09/09 09:34:00
duplicated for tryout... has to be reverted
 | 
| + Handle<ObjectHashTable> table, | 
| + Handle<Object> key, | 
| + Handle<Object> value) { | 
| + DCHECK(table->IsKey(*key)); | 
| + DCHECK(!value->IsTheHole()); | 
| + | 
| + // Make sure the key object has an identity hash code. | 
| + int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); | 
| + | 
| + return Put(isolate, table, key, value, hash); | 
| +} | 
| + | 
| + | 
| +Handle<ObjectHashTable> ObjectHashTable::Put(Isolate* isolate, | 
| + Handle<ObjectHashTable> table, | 
| + Handle<Object> key, | 
| + Handle<Object> value, | 
| + int32_t hash) { | 
| 
Camillo Bruni
2015/09/09 09:34:00
again, test duplication
 | 
| + DCHECK(table->IsKey(*key)); | 
| + DCHECK(!value->IsTheHole()); | 
| + | 
| + int entry = table->FindEntry(isolate, key, hash); | 
| + | 
| + // Key is already in table, just overwrite value. | 
| + if (entry != kNotFound) { | 
| + table->set(EntryToIndex(entry) + 1, *value); | 
| + return table; | 
| + } | 
| + | 
| + // Check whether the hash table should be extended. | 
| + table = EnsureCapacity(table, 1, key); | 
| + table->AddEntry(table->FindInsertionEntry(hash), *key, *value); | 
| + return table; | 
| +} | 
| + | 
| + | 
| Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table, | 
| Handle<Object> key, | 
| bool* was_present) { |