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 |