Chromium Code Reviews| 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/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <iomanip> | 7 #include <iomanip> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
| (...skipping 6462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6473 if (length == 0) { | 6473 if (length == 0) { |
| 6474 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 6474 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
| 6475 } | 6475 } |
| 6476 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 6476 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
| 6477 dictionary->CopyEnumKeysTo(*storage); | 6477 dictionary->CopyEnumKeysTo(*storage); |
| 6478 return storage; | 6478 return storage; |
| 6479 } | 6479 } |
| 6480 } | 6480 } |
| 6481 | 6481 |
| 6482 | 6482 |
| 6483 Handle<FixedArray> KeyAccumulator::GetKeys() { | |
| 6484 if (keys_.is_null()) { | |
| 6485 return isolate_->factory()->empty_fixed_array(); | |
| 6486 } | |
| 6487 keys_->Shrink(GetLength()); | |
| 6488 return keys_; | |
| 6489 } | |
| 6490 | |
| 6491 | |
| 6492 int KeyAccumulator::GetLength() { return length_; } | |
|
Igor Sheludko
2015/09/17 09:55:11
I think it's better to implement simple get/set me
| |
| 6493 | |
| 6494 | |
| 6495 void KeyAccumulator::AddKey(Handle<Object> key) { | |
| 6496 if (!set_.is_null()) { | |
| 6497 set_ = ObjectHashTable::Put(isolate_, set_, key, key); | |
| 6498 } | |
| 6499 EnsureCapacity(length_); | |
| 6500 keys_->set(length_, *key); | |
| 6501 length_++; | |
| 6502 } | |
| 6503 | |
| 6504 | |
| 6505 bool KeyAccumulator::HasKey(Handle<Object> key, int limit) { | |
| 6506 if (!set_.is_null()) { | |
| 6507 return set_->HasKey(isolate_, key); | |
| 6508 } | |
| 6509 // simple fallback in case we didn't use the set_ yet | |
| 6510 limit = Min(limit, length_); | |
| 6511 for (int i = 0; i < limit; i++) { | |
| 6512 Object* current = keys_->get(i); | |
| 6513 if (current->KeyEquals(*key)) return true; | |
| 6514 } | |
| 6515 return false; | |
| 6516 } | |
| 6517 | |
| 6518 | |
| 6519 void KeyAccumulator::AddKeys(Handle<FixedArray> array, | |
| 6520 FixedArray::KeyFilter filter) { | |
| 6521 int add_length = array->length(); | |
| 6522 if (add_length == 0) return; | |
| 6523 if (keys_.is_null() && filter == FixedArray::ALL_KEYS) { | |
| 6524 keys_ = array; | |
| 6525 length_ = keys_->length(); | |
| 6526 return; | |
| 6527 } | |
| 6528 PrepareForComparisons(add_length); | |
| 6529 int previous_key_count = length_; | |
| 6530 for (int i = 0; i < add_length; i++) { | |
| 6531 Handle<Object> current(array->get(i), isolate_); | |
| 6532 if (HasKey(current, previous_key_count)) continue; | |
| 6533 AddKey(current); | |
| 6534 } | |
| 6535 } | |
| 6536 | |
| 6537 | |
| 6538 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, | |
| 6539 FixedArray::KeyFilter filter) { | |
| 6540 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); | |
| 6541 ElementsAccessor* accessor = array_like->GetElementsAccessor(); | |
| 6542 accessor->AddElementsToFixedArrayWithAccumulator(array_like, this, filter); | |
| 6543 #ifdef ENABLE_SLOW_DCHECKS | |
| 6544 if (FLAG_enable_slow_asserts) { | |
| 6545 DisallowHeapAllocation no_allocation; | |
| 6546 for (int i = 0; i < GetLength(); i++) { | |
| 6547 Object* current = keys_->get(i); | |
| 6548 DCHECK(current->IsNumber() || current->IsName()); | |
| 6549 } | |
| 6550 } | |
| 6551 #endif | |
| 6552 } | |
| 6553 | |
| 6554 | |
| 6555 void KeyAccumulator::PrepareForComparisons(int count) { | |
| 6556 // Depending on how many comparisons we do we should switch to the | |
| 6557 // hash-table-based checks which have a high one-time overhead | |
| 6558 if (!set_.is_null()) return; | |
| 6559 // This is an unscientific guess for the threshold when we should | |
| 6560 // switch to the hash-table | |
| 6561 if (length_ * count < 100) return; | |
|
Camillo Bruni
2015/09/14 07:34:04
I tried a bit with different values and 100 turned
| |
| 6562 set_ = ObjectHashTable::New(isolate_, length_); | |
|
Camillo Bruni
2015/09/14 07:34:04
Technically this should be a set but we only have
Igor Sheludko
2015/09/17 09:55:11
Maybe it's worth implementing an ObjectHashSet. It
| |
| 6563 for (int i = 0; i < length_; i++) { | |
| 6564 Handle<Object> value(keys_->get(i), isolate_); | |
| 6565 set_ = ObjectHashTable::Put(isolate_, set_, value, value); | |
| 6566 } | |
| 6567 } | |
| 6568 | |
| 6569 | |
| 6570 void KeyAccumulator::EnsureCapacity(int capacity) { | |
| 6571 if (keys_.is_null() || keys_->length() <= capacity) { | |
| 6572 Grow(); | |
| 6573 } | |
| 6574 } | |
| 6575 | |
| 6576 | |
| 6577 void KeyAccumulator::Grow() { | |
| 6578 int capacity = keys_.is_null() ? 16 : keys_->length() * 2 + 16; | |
| 6579 Handle<FixedArray> new_keys = isolate_->factory()->NewFixedArray(capacity); | |
| 6580 if (keys_.is_null()) { | |
| 6581 keys_ = new_keys; | |
| 6582 return; | |
| 6583 } | |
| 6584 int buffer_length = keys_->length(); | |
| 6585 { | |
| 6586 DisallowHeapAllocation no_gc; | |
| 6587 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); | |
| 6588 for (int i = 0; i < buffer_length; i++) { | |
| 6589 new_keys->set(i, keys_->get(i), mode); | |
| 6590 } | |
| 6591 } | |
| 6592 keys_ = new_keys; | |
| 6593 } | |
| 6594 | |
| 6595 | |
| 6483 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 6596 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
| 6484 KeyCollectionType type) { | 6597 KeyCollectionType type) { |
| 6485 USE(ContainsOnlyValidKeys); | 6598 USE(ContainsOnlyValidKeys); |
| 6486 Isolate* isolate = object->GetIsolate(); | 6599 Isolate* isolate = object->GetIsolate(); |
| 6487 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); | 6600 KeyAccumulator accumulator(isolate); |
| 6488 Handle<JSFunction> arguments_function( | 6601 Handle<JSFunction> arguments_function( |
| 6489 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 6602 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
| 6490 | 6603 |
| 6491 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 6604 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
| 6492 ? PrototypeIterator::END_AT_NON_HIDDEN | 6605 ? PrototypeIterator::END_AT_NON_HIDDEN |
| 6493 : PrototypeIterator::END_AT_NULL; | 6606 : PrototypeIterator::END_AT_NULL; |
| 6494 // Only collect keys if access is permitted. | 6607 // Only collect keys if access is permitted. |
| 6495 for (PrototypeIterator iter(isolate, object, | 6608 for (PrototypeIterator iter(isolate, object, |
| 6496 PrototypeIterator::START_AT_RECEIVER); | 6609 PrototypeIterator::START_AT_RECEIVER); |
| 6497 !iter.IsAtEnd(end); iter.Advance()) { | 6610 !iter.IsAtEnd(end); iter.Advance()) { |
| 6498 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 6611 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| 6499 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); | 6612 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); |
| 6500 Handle<Object> args[] = { proxy }; | 6613 Handle<Object> args[] = { proxy }; |
| 6501 Handle<Object> names; | 6614 Handle<Object> names; |
| 6502 ASSIGN_RETURN_ON_EXCEPTION( | 6615 ASSIGN_RETURN_ON_EXCEPTION( |
| 6503 isolate, names, | 6616 isolate, names, |
| 6504 Execution::Call(isolate, | 6617 Execution::Call(isolate, |
| 6505 isolate->proxy_enumerate(), | 6618 isolate->proxy_enumerate(), |
| 6506 object, | 6619 object, |
| 6507 arraysize(args), | 6620 arraysize(args), |
| 6508 args), | 6621 args), |
| 6509 FixedArray); | 6622 FixedArray); |
| 6510 ASSIGN_RETURN_ON_EXCEPTION( | 6623 accumulator.AddKeys(Handle<JSObject>::cast(names), |
| 6511 isolate, content, | 6624 FixedArray::NON_SYMBOL_KEYS); |
| 6512 FixedArray::AddKeysFromArrayLike( | |
| 6513 content, Handle<JSObject>::cast(names)), | |
| 6514 FixedArray); | |
| 6515 break; | 6625 break; |
| 6516 } | 6626 } |
| 6517 | 6627 |
| 6518 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); | 6628 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); |
| 6519 | 6629 |
| 6520 // Check access rights if required. | 6630 // Check access rights if required. |
| 6521 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { | 6631 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { |
| 6522 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 6632 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
| 6523 isolate->ReportFailedAccessCheck(current); | 6633 isolate->ReportFailedAccessCheck(current); |
| 6524 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | 6634 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
| 6525 } | 6635 } |
| 6526 break; | 6636 break; |
| 6527 } | 6637 } |
| 6528 | 6638 |
| 6529 // Compute the element keys. | 6639 // Compute the element keys. |
| 6530 Handle<FixedArray> element_keys = | 6640 Handle<FixedArray> element_keys = |
| 6531 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); | 6641 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); |
| 6532 current->GetEnumElementKeys(*element_keys); | 6642 current->GetEnumElementKeys(*element_keys); |
| 6533 ASSIGN_RETURN_ON_EXCEPTION( | 6643 accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS); |
| 6534 isolate, content, | 6644 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
| 6535 FixedArray::UnionOfKeys(content, element_keys), | |
| 6536 FixedArray); | |
| 6537 DCHECK(ContainsOnlyValidKeys(content)); | |
| 6538 | 6645 |
| 6539 // Add the element keys from the interceptor. | 6646 // Add the element keys from the interceptor. |
| 6540 if (current->HasIndexedInterceptor()) { | 6647 if (current->HasIndexedInterceptor()) { |
| 6541 Handle<JSObject> result; | 6648 Handle<JSObject> result; |
| 6542 if (JSObject::GetKeysForIndexedInterceptor( | 6649 if (JSObject::GetKeysForIndexedInterceptor( |
| 6543 current, object).ToHandle(&result)) { | 6650 current, object).ToHandle(&result)) { |
| 6544 ASSIGN_RETURN_ON_EXCEPTION( | 6651 accumulator.AddKeys(result, FixedArray::ALL_KEYS); |
| 6545 isolate, content, | |
| 6546 FixedArray::AddKeysFromArrayLike(content, result), | |
| 6547 FixedArray); | |
| 6548 } | 6652 } |
| 6549 DCHECK(ContainsOnlyValidKeys(content)); | 6653 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
| 6550 } | 6654 } |
| 6551 | 6655 |
| 6552 // We can cache the computed property keys if access checks are | 6656 // We can cache the computed property keys if access checks are |
| 6553 // not needed and no interceptors are involved. | 6657 // not needed and no interceptors are involved. |
| 6554 // | 6658 // |
| 6555 // We do not use the cache if the object has elements and | 6659 // We do not use the cache if the object has elements and |
| 6556 // therefore it does not make sense to cache the property names | 6660 // therefore it does not make sense to cache the property names |
| 6557 // for arguments objects. Arguments objects will always have | 6661 // for arguments objects. Arguments objects will always have |
| 6558 // elements. | 6662 // elements. |
| 6559 // Wrapped strings have elements, but don't have an elements | 6663 // Wrapped strings have elements, but don't have an elements |
| 6560 // array or dictionary. So the fast inline test for whether to | 6664 // array or dictionary. So the fast inline test for whether to |
| 6561 // use the cache says yes, so we should not create a cache. | 6665 // use the cache says yes, so we should not create a cache. |
| 6562 bool cache_enum_keys = | 6666 bool cache_enum_keys = |
| 6563 ((current->map()->GetConstructor() != *arguments_function) && | 6667 ((current->map()->GetConstructor() != *arguments_function) && |
| 6564 !current->IsJSValue() && !current->IsAccessCheckNeeded() && | 6668 !current->IsJSValue() && !current->IsAccessCheckNeeded() && |
| 6565 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); | 6669 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); |
| 6566 // Compute the property keys and cache them if possible. | 6670 // Compute the property keys and cache them if possible. |
| 6567 ASSIGN_RETURN_ON_EXCEPTION( | 6671 |
| 6568 isolate, content, | 6672 Handle<FixedArray> enum_keys = |
| 6569 FixedArray::UnionOfKeys( | 6673 JSObject::GetEnumPropertyKeys(current, cache_enum_keys); |
| 6570 content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)), | 6674 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); |
| 6571 FixedArray); | 6675 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
| 6572 DCHECK(ContainsOnlyValidKeys(content)); | |
| 6573 | 6676 |
| 6574 // Add the non-symbol property keys from the interceptor. | 6677 // Add the non-symbol property keys from the interceptor. |
| 6575 if (current->HasNamedInterceptor()) { | 6678 if (current->HasNamedInterceptor()) { |
| 6576 Handle<JSObject> result; | 6679 Handle<JSObject> result; |
| 6577 if (JSObject::GetKeysForNamedInterceptor( | 6680 if (JSObject::GetKeysForNamedInterceptor( |
| 6578 current, object).ToHandle(&result)) { | 6681 current, object).ToHandle(&result)) { |
| 6579 ASSIGN_RETURN_ON_EXCEPTION( | 6682 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); |
| 6580 isolate, content, FixedArray::AddKeysFromArrayLike( | |
| 6581 content, result, FixedArray::NON_SYMBOL_KEYS), | |
| 6582 FixedArray); | |
| 6583 } | 6683 } |
| 6584 DCHECK(ContainsOnlyValidKeys(content)); | 6684 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
| 6585 } | 6685 } |
| 6586 } | 6686 } |
| 6587 return content; | 6687 |
| 6688 Handle<FixedArray> keys = accumulator.GetKeys(); | |
| 6689 DCHECK(ContainsOnlyValidKeys(keys)); | |
| 6690 return keys; | |
| 6588 } | 6691 } |
| 6589 | 6692 |
| 6590 | 6693 |
| 6591 bool Map::DictionaryElementsInPrototypeChainOnly() { | 6694 bool Map::DictionaryElementsInPrototypeChainOnly() { |
| 6592 if (IsDictionaryElementsKind(elements_kind())) { | 6695 if (IsDictionaryElementsKind(elements_kind())) { |
| 6593 return false; | 6696 return false; |
| 6594 } | 6697 } |
| 6595 | 6698 |
| 6596 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { | 6699 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { |
| 6597 // Be conservative, don't walk into proxies. | 6700 // Be conservative, don't walk into proxies. |
| (...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8078 | 8181 |
| 8079 void FixedArray::Shrink(int new_length) { | 8182 void FixedArray::Shrink(int new_length) { |
| 8080 DCHECK(0 <= new_length && new_length <= length()); | 8183 DCHECK(0 <= new_length && new_length <= length()); |
| 8081 if (new_length < length()) { | 8184 if (new_length < length()) { |
| 8082 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 8185 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
| 8083 this, length() - new_length); | 8186 this, length() - new_length); |
| 8084 } | 8187 } |
| 8085 } | 8188 } |
| 8086 | 8189 |
| 8087 | 8190 |
| 8088 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | |
| 8089 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) { | |
| 8090 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); | |
| 8091 ElementsAccessor* accessor = array->GetElementsAccessor(); | |
| 8092 Handle<FixedArray> result = | |
| 8093 accessor->AddElementsToFixedArray(array, content, filter); | |
| 8094 | |
| 8095 #ifdef ENABLE_SLOW_DCHECKS | |
| 8096 if (FLAG_enable_slow_asserts) { | |
| 8097 DisallowHeapAllocation no_allocation; | |
| 8098 for (int i = 0; i < result->length(); i++) { | |
| 8099 Object* current = result->get(i); | |
| 8100 DCHECK(current->IsNumber() || current->IsName()); | |
| 8101 } | |
| 8102 } | |
| 8103 #endif | |
| 8104 return result; | |
| 8105 } | |
| 8106 | |
| 8107 | |
| 8108 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, | |
| 8109 Handle<FixedArray> second) { | |
| 8110 if (second->length() == 0) return first; | |
| 8111 if (first->length() == 0) return second; | |
| 8112 Isolate* isolate = first->GetIsolate(); | |
| 8113 Handle<FixedArray> result = | |
| 8114 isolate->factory()->NewFixedArray(first->length() + second->length()); | |
| 8115 for (int i = 0; i < first->length(); i++) { | |
| 8116 result->set(i, first->get(i)); | |
| 8117 } | |
| 8118 int pos = first->length(); | |
| 8119 for (int j = 0; j < second->length(); j++) { | |
| 8120 Object* current = second->get(j); | |
| 8121 int i; | |
| 8122 for (i = 0; i < first->length(); i++) { | |
| 8123 if (current->KeyEquals(first->get(i))) break; | |
| 8124 } | |
| 8125 if (i == first->length()) { | |
| 8126 result->set(pos++, current); | |
| 8127 } | |
| 8128 } | |
| 8129 | |
| 8130 result->Shrink(pos); | |
| 8131 return result; | |
| 8132 } | |
| 8133 | |
| 8134 | |
| 8135 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { | 8191 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { |
| 8136 DisallowHeapAllocation no_gc; | 8192 DisallowHeapAllocation no_gc; |
| 8137 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); | 8193 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); |
| 8138 for (int index = 0; index < len; index++) { | 8194 for (int index = 0; index < len; index++) { |
| 8139 dest->set(dest_pos+index, get(pos+index), mode); | 8195 dest->set(dest_pos+index, get(pos+index), mode); |
| 8140 } | 8196 } |
| 8141 } | 8197 } |
| 8142 | 8198 |
| 8143 | 8199 |
| 8144 #ifdef DEBUG | 8200 #ifdef DEBUG |
| (...skipping 7075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15220 e = PropertyCell::cast(e)->value(); | 15276 e = PropertyCell::cast(e)->value(); |
| 15221 } | 15277 } |
| 15222 if (e == value) return k; | 15278 if (e == value) return k; |
| 15223 } | 15279 } |
| 15224 } | 15280 } |
| 15225 Heap* heap = Dictionary::GetHeap(); | 15281 Heap* heap = Dictionary::GetHeap(); |
| 15226 return heap->undefined_value(); | 15282 return heap->undefined_value(); |
| 15227 } | 15283 } |
| 15228 | 15284 |
| 15229 | 15285 |
| 15286 bool ObjectHashTable::HasKey(Isolate* isolate, Handle<Object> key) { | |
| 15287 DisallowHeapAllocation no_gc; | |
| 15288 DCHECK(IsKey(*key)); | |
| 15289 | |
| 15290 // If the object does not have an identity hash, it was never used as a key. | |
| 15291 Object* hash = key->GetHash(); | |
| 15292 if (hash->IsUndefined()) return false; | |
| 15293 | |
| 15294 int entry = FindEntry(isolate, key, Smi::cast(hash)->value()); | |
| 15295 return entry != kNotFound; | |
| 15296 } | |
| 15297 | |
| 15298 | |
| 15230 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key, | 15299 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key, |
| 15231 int32_t hash) { | 15300 int32_t hash) { |
| 15232 DisallowHeapAllocation no_gc; | 15301 DisallowHeapAllocation no_gc; |
| 15233 DCHECK(IsKey(*key)); | 15302 DCHECK(IsKey(*key)); |
| 15234 | 15303 |
| 15235 int entry = FindEntry(isolate, key, hash); | 15304 int entry = FindEntry(isolate, key, hash); |
| 15236 if (entry == kNotFound) return isolate->heap()->the_hole_value(); | 15305 if (entry == kNotFound) return isolate->heap()->the_hole_value(); |
| 15237 return get(EntryToIndex(entry) + 1); | 15306 return get(EntryToIndex(entry) + 1); |
| 15238 } | 15307 } |
| 15239 | 15308 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 15254 | 15323 |
| 15255 | 15324 |
| 15256 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { | 15325 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { |
| 15257 return Lookup(GetIsolate(), key, hash); | 15326 return Lookup(GetIsolate(), key, hash); |
| 15258 } | 15327 } |
| 15259 | 15328 |
| 15260 | 15329 |
| 15261 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 15330 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 15262 Handle<Object> key, | 15331 Handle<Object> key, |
| 15263 Handle<Object> value) { | 15332 Handle<Object> value) { |
| 15333 return Put(table->GetIsolate(), table, key, value); | |
| 15334 } | |
| 15335 | |
| 15336 | |
| 15337 Handle<ObjectHashTable> ObjectHashTable::Put(Isolate* isolate, | |
| 15338 Handle<ObjectHashTable> table, | |
| 15339 Handle<Object> key, | |
| 15340 Handle<Object> value) { | |
| 15264 DCHECK(table->IsKey(*key)); | 15341 DCHECK(table->IsKey(*key)); |
| 15265 DCHECK(!value->IsTheHole()); | 15342 DCHECK(!value->IsTheHole()); |
| 15266 | 15343 |
| 15267 Isolate* isolate = table->GetIsolate(); | |
| 15268 // Make sure the key object has an identity hash code. | 15344 // Make sure the key object has an identity hash code. |
| 15269 int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); | 15345 int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); |
| 15270 | 15346 |
| 15271 return Put(table, key, value, hash); | 15347 return Put(isolate, table, key, value, hash); |
| 15272 } | 15348 } |
| 15273 | 15349 |
| 15274 | 15350 |
| 15275 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 15351 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 15276 Handle<Object> key, | 15352 Handle<Object> key, |
| 15277 Handle<Object> value, | 15353 Handle<Object> value, |
| 15278 int32_t hash) { | 15354 int32_t hash) { |
| 15355 return Put(table->GetIsolate(), table, key, value, hash); | |
| 15356 } | |
| 15357 | |
| 15358 | |
| 15359 Handle<ObjectHashTable> ObjectHashTable::Put(Isolate* isolate, | |
| 15360 Handle<ObjectHashTable> table, | |
| 15361 Handle<Object> key, | |
| 15362 Handle<Object> value, | |
| 15363 int32_t hash) { | |
| 15279 DCHECK(table->IsKey(*key)); | 15364 DCHECK(table->IsKey(*key)); |
| 15280 DCHECK(!value->IsTheHole()); | 15365 DCHECK(!value->IsTheHole()); |
| 15281 | 15366 |
| 15282 Isolate* isolate = table->GetIsolate(); | |
| 15283 | |
| 15284 int entry = table->FindEntry(isolate, key, hash); | 15367 int entry = table->FindEntry(isolate, key, hash); |
| 15285 | 15368 |
| 15286 // Key is already in table, just overwrite value. | 15369 // Key is already in table, just overwrite value. |
| 15287 if (entry != kNotFound) { | 15370 if (entry != kNotFound) { |
| 15288 table->set(EntryToIndex(entry) + 1, *value); | 15371 table->set(EntryToIndex(entry) + 1, *value); |
| 15289 return table; | 15372 return table; |
| 15290 } | 15373 } |
| 15291 | 15374 |
| 15292 // Check whether the hash table should be extended. | 15375 // Check whether the hash table should be extended. |
| 15293 table = EnsureCapacity(table, 1, key); | 15376 table = EnsureCapacity(table, 1, key); |
| (...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16352 if (cell->value() != *new_value) { | 16435 if (cell->value() != *new_value) { |
| 16353 cell->set_value(*new_value); | 16436 cell->set_value(*new_value); |
| 16354 Isolate* isolate = cell->GetIsolate(); | 16437 Isolate* isolate = cell->GetIsolate(); |
| 16355 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16438 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16356 isolate, DependentCode::kPropertyCellChangedGroup); | 16439 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16357 } | 16440 } |
| 16358 } | 16441 } |
| 16359 | 16442 |
| 16360 } // namespace internal | 16443 } // namespace internal |
| 16361 } // namespace v8 | 16444 } // namespace v8 |
| OLD | NEW |