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 <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
11 #include "src/accessors.h" | 11 #include "src/accessors.h" |
12 #include "src/allocation-site-scopes.h" | 12 #include "src/allocation-site-scopes.h" |
13 #include "src/api.h" | 13 #include "src/api.h" |
14 #include "src/arguments.h" | 14 #include "src/arguments.h" |
15 #include "src/base/bits.h" | 15 #include "src/base/bits.h" |
16 #include "src/base/utils/random-number-generator.h" | 16 #include "src/base/utils/random-number-generator.h" |
17 #include "src/bootstrapper.h" | 17 #include "src/bootstrapper.h" |
18 #include "src/code-stubs.h" | 18 #include "src/code-stubs.h" |
19 #include "src/codegen.h" | 19 #include "src/codegen.h" |
20 #include "src/compilation-dependencies.h" | 20 #include "src/compilation-dependencies.h" |
21 #include "src/compiler.h" | 21 #include "src/compiler.h" |
22 #include "src/date.h" | 22 #include "src/date.h" |
23 #include "src/debug/debug.h" | 23 #include "src/debug/debug.h" |
24 #include "src/deoptimizer.h" | 24 #include "src/deoptimizer.h" |
25 #include "src/elements.h" | 25 #include "src/elements.h" |
26 #include "src/execution.h" | 26 #include "src/execution.h" |
27 #include "src/field-index.h" | |
27 #include "src/field-index-inl.h" | 28 #include "src/field-index-inl.h" |
28 #include "src/field-index.h" | |
29 #include "src/full-codegen/full-codegen.h" | 29 #include "src/full-codegen/full-codegen.h" |
30 #include "src/hydrogen.h" | 30 #include "src/hydrogen.h" |
31 #include "src/ic/ic.h" | 31 #include "src/ic/ic.h" |
32 #include "src/interpreter/bytecodes.h" | 32 #include "src/interpreter/bytecodes.h" |
33 #include "src/isolate-inl.h" | 33 #include "src/isolate-inl.h" |
34 #include "src/list.h" | |
34 #include "src/log.h" | 35 #include "src/log.h" |
35 #include "src/lookup.h" | 36 #include "src/lookup.h" |
36 #include "src/macro-assembler.h" | 37 #include "src/macro-assembler.h" |
37 #include "src/messages.h" | 38 #include "src/messages.h" |
38 #include "src/objects-inl.h" | 39 #include "src/objects-inl.h" |
39 #include "src/profiler/cpu-profiler.h" | 40 #include "src/profiler/cpu-profiler.h" |
40 #include "src/property-descriptor.h" | 41 #include "src/property-descriptor.h" |
41 #include "src/prototype.h" | 42 #include "src/prototype.h" |
42 #include "src/safepoint-table.h" | 43 #include "src/safepoint-table.h" |
43 #include "src/string-builder.h" | 44 #include "src/string-builder.h" |
(...skipping 7278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7322 if (current->IsAccessCheckNeeded()) return false; | 7323 if (current->IsAccessCheckNeeded()) return false; |
7323 DCHECK(!current->HasNamedInterceptor()); | 7324 DCHECK(!current->HasNamedInterceptor()); |
7324 DCHECK(!current->HasIndexedInterceptor()); | 7325 DCHECK(!current->HasIndexedInterceptor()); |
7325 if (current->NumberOfEnumElements() > 0) return false; | 7326 if (current->NumberOfEnumElements() > 0) return false; |
7326 if (current != this && enum_length != 0) return false; | 7327 if (current != this && enum_length != 0) return false; |
7327 } | 7328 } |
7328 return true; | 7329 return true; |
7329 } | 7330 } |
7330 | 7331 |
7331 | 7332 |
7332 static bool FilterKey(Object* key, PropertyAttributes filter) { | |
7333 if ((filter & SYMBOLIC) && key->IsSymbol()) { | |
7334 return true; | |
7335 } | |
7336 | |
7337 if ((filter & PRIVATE_SYMBOL) && | |
7338 key->IsSymbol() && Symbol::cast(key)->is_private()) { | |
7339 return true; | |
7340 } | |
7341 | |
7342 if ((filter & STRING) && !key->IsSymbol()) { | |
7343 return true; | |
7344 } | |
7345 | |
7346 return false; | |
7347 } | |
7348 | |
7349 | |
7350 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 7333 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
7351 PropertyAttributes filter) { | 7334 PropertyAttributes filter) { |
7352 int result = 0; | 7335 int result = 0; |
7353 DescriptorArray* descs = instance_descriptors(); | 7336 DescriptorArray* descs = instance_descriptors(); |
7354 int limit = which == ALL_DESCRIPTORS | 7337 int limit = which == ALL_DESCRIPTORS |
7355 ? descs->number_of_descriptors() | 7338 ? descs->number_of_descriptors() |
7356 : NumberOfOwnDescriptors(); | 7339 : NumberOfOwnDescriptors(); |
7357 for (int i = 0; i < limit; i++) { | 7340 for (int i = 0; i < limit; i++) { |
7358 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 7341 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
7359 !FilterKey(descs->GetKey(i), filter)) { | 7342 !descs->GetKey(i)->FilterKey(filter)) { |
7360 result++; | 7343 result++; |
7361 } | 7344 } |
7362 } | 7345 } |
7363 return result; | 7346 return result; |
7364 } | 7347 } |
7365 | 7348 |
7366 | 7349 |
7367 int Map::NextFreePropertyIndex() { | 7350 int Map::NextFreePropertyIndex() { |
7368 int free_index = 0; | 7351 int free_index = 0; |
7369 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 7352 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7500 if (length == 0) { | 7483 if (length == 0) { |
7501 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 7484 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
7502 } | 7485 } |
7503 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 7486 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
7504 dictionary->CopyEnumKeysTo(*storage); | 7487 dictionary->CopyEnumKeysTo(*storage); |
7505 return storage; | 7488 return storage; |
7506 } | 7489 } |
7507 } | 7490 } |
7508 | 7491 |
7509 | 7492 |
7510 Handle<FixedArray> KeyAccumulator::GetKeys() { | 7493 KeyAccumulator::~KeyAccumulator() { |
7494 for (int i = 0; i < elements_.length(); i++) { | |
7495 delete elements_[i]; | |
7496 } | |
7497 } | |
7498 | |
7499 | |
7500 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | |
7511 if (length_ == 0) { | 7501 if (length_ == 0) { |
7512 return isolate_->factory()->empty_fixed_array(); | 7502 return isolate_->factory()->empty_fixed_array(); |
7513 } | 7503 } |
7514 if (set_.is_null()) { | 7504 // make sure we have all the lengths collected |
Igor Sheludko
2015/10/19 13:11:19
Make ... collected.
| |
7515 keys_->Shrink(length_); | 7505 NextPrototype(); |
7516 return keys_; | 7506 |
7517 } | 7507 // Assemble the result array by first adding the element keys and then |
7518 // copy over results from set_ | 7508 // the property keys. We use the total number of keys per level in |
7509 // |protoLengths_| and the available element keys in the corresponding bucket | |
7510 // in |elements_| to deduce the number of keys to take from the |properties_| | |
7511 // set. | |
7519 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); | 7512 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); |
7520 for (int i = 0; i < length_; i++) { | 7513 int index = 0; |
7521 result->set(i, set_->KeyAt(i)); | 7514 int properties_index = 0; |
7522 } | 7515 for (int level = 0; level < levelLengths_.length(); level++) { |
7516 int num_total = levelLengths_[level]; | |
7517 int num_elements = 0; | |
7518 if (num_total < 0) { | |
7519 // If the total is negative, the current level contains properties from a | |
7520 // proxy, hence we skip the integer keys in |elements_| since proxies | |
7521 // define the complete ordering. | |
7522 num_total = -num_total; | |
7523 } else if (level < elements_.length()) { | |
7524 List<uint32_t>* elements = elements_[level]; | |
7525 num_elements = elements->length(); | |
7526 for (int i = 0; i < num_elements; i++) { | |
7527 Handle<Object> key; | |
7528 if (convert == KEEP_NUMBERS) { | |
7529 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); | |
7530 } else { | |
7531 key = isolate_->factory()->Uint32ToString(elements->at(i)); | |
7532 } | |
7533 result->set(index, *key); | |
7534 index++; | |
7535 } | |
7536 } | |
7537 // Add the property keys for this prototype level. | |
7538 int num_properties = num_total - num_elements; | |
7539 for (int i = 0; i < num_properties; i++) { | |
7540 Object* key = properties_->KeyAt(properties_index); | |
7541 result->set(index, key); | |
7542 index++; | |
7543 properties_index++; | |
7544 } | |
7545 } | |
7546 DCHECK_EQ(index, length_); | |
7523 return result; | 7547 return result; |
7524 } | 7548 } |
7525 | 7549 |
7526 | 7550 |
7527 void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) { | 7551 namespace { |
7528 #ifdef ENABLE_SLOW_DCHECKS | 7552 |
7529 if (FLAG_enable_slow_asserts) { | 7553 class FindKey { |
7530 DCHECK(key->IsNumber() || key->IsName()); | 7554 public: |
7531 } | 7555 explicit FindKey(uint32_t key) : key_(key) {} |
7532 #endif | 7556 int operator()(uint32_t* entry) { |
7533 if (!set_.is_null()) { | 7557 if (*entry == key_) return 0; |
7534 set_ = OrderedHashSet::Add(set_, key); | 7558 return *entry < key_ ? -1 : 1; |
7535 length_ = set_->NumberOfElements(); | 7559 } |
7536 return; | 7560 |
7537 } | 7561 private: |
7538 // check if we already have the key in the case we are still using | 7562 uint32_t key_; |
7539 // the keys_ FixedArray | 7563 }; |
7540 check_limit = Min(check_limit, length_); | 7564 |
7541 for (int i = 0; i < check_limit; i++) { | 7565 |
7542 Object* current = keys_->get(i); | 7566 bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) { |
7543 if (current->KeyEquals(*key)) return; | 7567 int index = SortedListBSearch(*sub_elements, FindKey(key)); |
7544 } | 7568 return index != -1; |
7545 EnsureCapacity(length_); | 7569 } |
7546 keys_->set(length_, *key); | 7570 |
7571 } // namespace | |
7572 | |
7573 | |
7574 bool KeyAccumulator::AddKey(uint32_t key) { | |
7575 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | |
7576 DCHECK_LE(0, levelLength_); | |
7577 int lookup_limit = elements_.length(); | |
7578 for (int i = 0; i < lookup_limit; i++) { | |
7579 if (AccumulatorHasKey(elements_[i], key)) return false; | |
7580 } | |
7581 elements_[lookup_limit - 1]->Add(key); | |
7547 length_++; | 7582 length_++; |
7548 } | 7583 levelLength_++; |
7549 | 7584 return true; |
7550 | 7585 } |
7551 void KeyAccumulator::AddKeys(Handle<FixedArray> array, KeyFilter filter) { | 7586 |
7587 | |
7588 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { | |
7589 return AddKey(handle(key, isolate_), convert); | |
7590 } | |
7591 | |
7592 | |
7593 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { | |
7594 if (filter_ == SKIP_SYMBOLS && key->IsSymbol()) { | |
7595 return false; | |
7596 } | |
7597 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | |
7598 DCHECK_LE(0, levelLength_); | |
7599 // In some cases (e.g. proxies) we might get in String-converted ints which | |
7600 // should be added to the elements list instead of the properties. For | |
7601 // proxies we have to convert as well but also respect the original order. | |
7602 // Therefore we add a converted key to both sides | |
7603 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) { | |
7604 uint32_t index = 0; | |
7605 int prev_length = length_; | |
7606 int prev_proto = levelLength_; | |
7607 bool was_array_index = false; | |
7608 bool key_was_added = false; | |
7609 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) || | |
7610 key->ToArrayIndex(&index)) { | |
7611 key_was_added = AddKey(index); | |
7612 was_array_index = true; | |
7613 if (convert == CONVERT_TO_ARRAY_INDEX) return key_was_added; | |
7614 } | |
7615 if (was_array_index && convert == PROXY_MAGIC) { | |
7616 // If we had an array index (number) and it wasn't added, the key | |
7617 // already existed before, hence we cannot add it to the properties | |
7618 // keys as it would lead to duplicate entries. | |
7619 if (!key_was_added) { | |
7620 return false; | |
7621 } | |
7622 length_ = prev_length; | |
7623 levelLength_ = prev_proto; | |
7624 } | |
7625 } | |
7626 if (properties_.is_null()) { | |
7627 properties_ = OrderedHashSet::Allocate(isolate_, 16); | |
7628 } | |
7629 // TODO(cbruni): remove this conversion once we throw the correct TypeError | |
7630 // for non-string/symbol elements returned by proxies | |
7631 if (convert == PROXY_MAGIC && key->IsNumber()) { | |
7632 key = isolate_->factory()->NumberToString(key); | |
7633 } | |
7634 int prev_size = properties_->NumberOfElements(); | |
7635 properties_ = OrderedHashSet::Add(properties_, key); | |
7636 if (prev_size < properties_->NumberOfElements()) { | |
7637 length_++; | |
7638 levelLength_++; | |
7639 } | |
7640 return true; | |
7641 } | |
7642 | |
7643 | |
7644 void KeyAccumulator::AddKeys(Handle<FixedArray> array, | |
7645 AddKeyConversion convert) { | |
7552 int add_length = array->length(); | 7646 int add_length = array->length(); |
7553 if (add_length == 0) return; | 7647 if (add_length == 0) return; |
7554 if (keys_.is_null() && filter == INCLUDE_SYMBOLS) { | |
7555 keys_ = array; | |
7556 length_ = keys_->length(); | |
7557 return; | |
7558 } | |
7559 PrepareForComparisons(add_length); | |
7560 int previous_key_count = length_; | |
7561 for (int i = 0; i < add_length; i++) { | 7648 for (int i = 0; i < add_length; i++) { |
7562 Handle<Object> current(array->get(i), isolate_); | 7649 Handle<Object> current(array->get(i), isolate_); |
7563 if (filter == SKIP_SYMBOLS && current->IsSymbol()) continue; | 7650 AddKey(current); |
7564 AddKey(current, previous_key_count); | 7651 } |
7565 } | 7652 } |
7566 } | 7653 |
7567 | 7654 |
7568 | 7655 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, |
7569 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, KeyFilter filter) { | 7656 AddKeyConversion convert) { |
7570 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); | 7657 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); |
7571 ElementsAccessor* accessor = array_like->GetElementsAccessor(); | 7658 ElementsAccessor* accessor = array_like->GetElementsAccessor(); |
7572 accessor->AddElementsToKeyAccumulator(array_like, this, filter); | 7659 accessor->AddElementsToKeyAccumulator(array_like, this, convert); |
7573 } | 7660 } |
7574 | 7661 |
7575 | 7662 |
7576 void KeyAccumulator::PrepareForComparisons(int count) { | 7663 void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) { |
7577 // Depending on how many comparisons we do we should switch to the | 7664 // Proxies define a complete list of keys with no distinction of |
7578 // hash-table-based checks which have a one-time overhead for | 7665 // elements and properties, which breaks the normal assumption for the |
7579 // initializing but O(1) for HasKey checks. | 7666 // KeyAccumulator. |
7580 if (!set_.is_null()) return; | 7667 AddKeys(array_like, PROXY_MAGIC); |
7581 // These limits were obtained through evaluation of several microbenchmarks. | 7668 // Invert the current length to indicate a present proxy, so we can ignore |
7582 if (length_ * count < 100) return; | 7669 // element keys for this level. Otherwise we would not fully respect the order |
7583 // Don't use a set for few elements | 7670 // given by the proxy. |
7584 if (length_ < 100 && count < 20) return; | 7671 levelLength_ = -levelLength_; |
7585 set_ = OrderedHashSet::Allocate(isolate_, length_); | 7672 } |
7586 for (int i = 0; i < length_; i++) { | 7673 |
7587 Handle<Object> value(keys_->get(i), isolate_); | 7674 |
7588 set_ = OrderedHashSet::Add(set_, value); | 7675 namespace { |
7589 } | 7676 |
7590 } | 7677 // Used for sorting indices in a List<uint32_t>. |
7591 | 7678 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { |
7592 | 7679 uint32_t a = *ap; |
7593 void KeyAccumulator::EnsureCapacity(int capacity) { | 7680 uint32_t b = *bp; |
7594 if (keys_.is_null() || keys_->length() <= capacity) { | 7681 return (a == b) ? 0 : (a < b) ? -1 : 1; |
7595 Grow(); | 7682 } |
7596 } | 7683 |
7597 } | 7684 |
7598 | 7685 } // namespace |
7599 | 7686 |
7600 void KeyAccumulator::Grow() { | 7687 |
7601 // The OrderedHashSet handles growing by itself. | 7688 void KeyAccumulator::SortCurrentElementsList() { |
7602 if (!set_.is_null()) return; | 7689 if (elements_.length() == 0) return; |
7603 // Otherwise, grow the internal keys_ FixedArray | 7690 List<uint32_t>* element_keys = elements_[elements_.length() - 1]; |
7604 int capacity = keys_.is_null() ? 16 : keys_->length() * 2 + 16; | 7691 element_keys->Sort(&compareUInt32); |
7605 Handle<FixedArray> new_keys = isolate_->factory()->NewFixedArray(capacity); | 7692 } |
7606 if (keys_.is_null()) { | 7693 |
7607 keys_ = new_keys; | 7694 |
7608 return; | 7695 void KeyAccumulator::NextPrototype() { |
7609 } | 7696 // Store the protoLength on the first call of this method. |
7610 int buffer_length = keys_->length(); | 7697 if (!elements_.is_empty()) { |
7611 { | 7698 levelLengths_.Add(levelLength_); |
7612 DisallowHeapAllocation no_gc; | 7699 } |
7613 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); | 7700 elements_.Add(new List<uint32_t>()); |
7614 for (int i = 0; i < buffer_length; i++) { | 7701 levelLength_ = 0; |
7615 new_keys->set(i, keys_->get(i), mode); | |
7616 } | |
7617 } | |
7618 keys_ = new_keys; | |
7619 } | 7702 } |
7620 | 7703 |
7621 | 7704 |
7622 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 7705 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
7623 KeyCollectionType type, | 7706 KeyCollectionType type, |
7624 KeyFilter filter) { | 7707 KeyFilter filter, |
7708 GetKeysConversion getConversion) { | |
7625 USE(ContainsOnlyValidKeys); | 7709 USE(ContainsOnlyValidKeys); |
7626 Isolate* isolate = object->GetIsolate(); | 7710 Isolate* isolate = object->GetIsolate(); |
7627 KeyAccumulator accumulator(isolate); | 7711 KeyAccumulator accumulator(isolate, filter); |
7628 Handle<JSFunction> arguments_function( | 7712 Handle<JSFunction> arguments_function( |
7629 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 7713 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
7630 | 7714 |
7631 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 7715 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
7632 ? PrototypeIterator::END_AT_NON_HIDDEN | 7716 ? PrototypeIterator::END_AT_NON_HIDDEN |
7633 : PrototypeIterator::END_AT_NULL; | 7717 : PrototypeIterator::END_AT_NULL; |
7634 // Only collect keys if access is permitted. | 7718 // Only collect keys if access is permitted. |
7635 for (PrototypeIterator iter(isolate, object, | 7719 for (PrototypeIterator iter(isolate, object, |
7636 PrototypeIterator::START_AT_RECEIVER); | 7720 PrototypeIterator::START_AT_RECEIVER); |
7637 !iter.IsAtEnd(end); iter.Advance()) { | 7721 !iter.IsAtEnd(end); iter.Advance()) { |
7722 accumulator.NextPrototype(); | |
7638 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 7723 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
7639 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); | 7724 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); |
7640 Handle<Object> args[] = { proxy }; | 7725 Handle<Object> args[] = { proxy }; |
7641 Handle<Object> names; | 7726 Handle<Object> names; |
7642 ASSIGN_RETURN_ON_EXCEPTION( | 7727 ASSIGN_RETURN_ON_EXCEPTION( |
7643 isolate, names, | 7728 isolate, names, |
7644 Execution::Call(isolate, | 7729 Execution::Call(isolate, |
7645 isolate->proxy_enumerate(), | 7730 isolate->proxy_enumerate(), |
7646 object, | 7731 object, |
7647 arraysize(args), | 7732 arraysize(args), |
7648 args), | 7733 args), |
7649 FixedArray); | 7734 FixedArray); |
7650 accumulator.AddKeys(Handle<JSObject>::cast(names), filter); | 7735 accumulator.AddKeysFromProxy(Handle<JSObject>::cast(names)); |
7651 break; | 7736 break; |
7652 } | 7737 } |
7653 | 7738 |
7654 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); | 7739 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); |
7655 | 7740 |
7656 // Check access rights if required. | 7741 // Check access rights if required. |
7657 if (current->IsAccessCheckNeeded() && | 7742 if (current->IsAccessCheckNeeded() && |
7658 !isolate->MayAccess(handle(isolate->context()), current)) { | 7743 !isolate->MayAccess(handle(isolate->context()), current)) { |
7659 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 7744 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
7660 isolate->ReportFailedAccessCheck(current); | 7745 isolate->ReportFailedAccessCheck(current); |
7661 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | 7746 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
7662 } | 7747 } |
7663 break; | 7748 break; |
7664 } | 7749 } |
7665 | 7750 |
7666 // Compute the element keys. | 7751 JSObject::CollectOwnElementKeys(current, &accumulator, |
7667 Handle<FixedArray> element_keys = | 7752 static_cast<PropertyAttributes>(DONT_ENUM)); |
7668 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); | |
7669 current->GetEnumElementKeys(*element_keys); | |
7670 accumulator.AddKeys(element_keys, filter); | |
7671 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | |
7672 | 7753 |
7673 // Add the element keys from the interceptor. | 7754 // Add the element keys from the interceptor. |
7674 if (current->HasIndexedInterceptor()) { | 7755 if (current->HasIndexedInterceptor()) { |
7675 Handle<JSObject> result; | 7756 Handle<JSObject> result; |
7676 if (JSObject::GetKeysForIndexedInterceptor( | 7757 if (JSObject::GetKeysForIndexedInterceptor(current, object) |
7677 current, object).ToHandle(&result)) { | 7758 .ToHandle(&result)) { |
7678 accumulator.AddKeys(result, filter); | 7759 accumulator.AddKeys(result, CONVERT_TO_ARRAY_INDEX); |
7679 } | 7760 } |
7680 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | |
7681 } | 7761 } |
7682 | 7762 |
7683 if (filter == SKIP_SYMBOLS) { | 7763 if (filter == SKIP_SYMBOLS) { |
7684 // We can cache the computed property keys if access checks are | 7764 // We can cache the computed property keys if access checks are |
7685 // not needed and no interceptors are involved. | 7765 // not needed and no interceptors are involved. |
7686 // | 7766 // |
7687 // We do not use the cache if the object has elements and | 7767 // We do not use the cache if the object has elements and |
7688 // therefore it does not make sense to cache the property names | 7768 // therefore it does not make sense to cache the property names |
7689 // for arguments objects. Arguments objects will always have | 7769 // for arguments objects. Arguments objects will always have |
7690 // elements. | 7770 // elements. |
7691 // Wrapped strings have elements, but don't have an elements | 7771 // Wrapped strings have elements, but don't have an elements |
7692 // array or dictionary. So the fast inline test for whether to | 7772 // array or dictionary. So the fast inline test for whether to |
7693 // use the cache says yes, so we should not create a cache. | 7773 // use the cache says yes, so we should not create a cache. |
7694 bool cache_enum_length = | 7774 bool cache_enum_length = |
7695 ((current->map()->GetConstructor() != *arguments_function) && | 7775 ((current->map()->GetConstructor() != *arguments_function) && |
7696 !current->IsJSValue() && !current->IsAccessCheckNeeded() && | 7776 !current->IsJSValue() && !current->IsAccessCheckNeeded() && |
7697 !current->HasNamedInterceptor() && | 7777 !current->HasNamedInterceptor() && |
7698 !current->HasIndexedInterceptor()); | 7778 !current->HasIndexedInterceptor()); |
7699 // Compute the property keys and cache them if possible. | 7779 // Compute the property keys and cache them if possible. |
7700 | |
7701 Handle<FixedArray> enum_keys = | 7780 Handle<FixedArray> enum_keys = |
7702 JSObject::GetEnumPropertyKeys(current, cache_enum_length); | 7781 JSObject::GetEnumPropertyKeys(current, cache_enum_length); |
7703 accumulator.AddKeys(enum_keys, filter); | 7782 accumulator.AddKeys(enum_keys); |
7704 } else { | 7783 } else { |
7705 DCHECK(filter == INCLUDE_SYMBOLS); | 7784 DCHECK(filter == INCLUDE_SYMBOLS); |
7706 PropertyAttributes attr_filter = | 7785 PropertyAttributes attr_filter = |
7707 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); | 7786 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); |
7708 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( | 7787 JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter); |
7709 current->NumberOfOwnProperties(attr_filter)); | |
7710 current->GetOwnPropertyNames(*property_keys, 0, attr_filter); | |
7711 accumulator.AddKeys(property_keys, filter); | |
7712 } | 7788 } |
7713 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | |
7714 | 7789 |
7715 // Add the property keys from the interceptor. | 7790 // Add the property keys from the interceptor. |
7716 if (current->HasNamedInterceptor()) { | 7791 if (current->HasNamedInterceptor()) { |
7717 Handle<JSObject> result; | 7792 Handle<JSObject> result; |
7718 if (JSObject::GetKeysForNamedInterceptor( | 7793 if (JSObject::GetKeysForNamedInterceptor(current, object) |
7719 current, object).ToHandle(&result)) { | 7794 .ToHandle(&result)) { |
7720 accumulator.AddKeys(result, filter); | 7795 accumulator.AddKeys(result); |
7721 } | 7796 } |
7722 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | |
7723 } | 7797 } |
7724 } | 7798 } |
7725 | 7799 |
7726 Handle<FixedArray> keys = accumulator.GetKeys(); | 7800 Handle<FixedArray> keys = accumulator.GetKeys(getConversion); |
7727 DCHECK(ContainsOnlyValidKeys(keys)); | 7801 DCHECK(ContainsOnlyValidKeys(keys)); |
7728 return keys; | 7802 return keys; |
7729 } | 7803 } |
7730 | 7804 |
7731 | 7805 |
7732 bool Map::DictionaryElementsInPrototypeChainOnly() { | 7806 bool Map::DictionaryElementsInPrototypeChainOnly() { |
7733 if (IsDictionaryElementsKind(elements_kind())) { | 7807 if (IsDictionaryElementsKind(elements_kind())) { |
7734 return false; | 7808 return false; |
7735 } | 7809 } |
7736 | 7810 |
(...skipping 6936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14673 // mirrors. | 14747 // mirrors. |
14674 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, | 14748 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, |
14675 PropertyAttributes filter) { | 14749 PropertyAttributes filter) { |
14676 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); | 14750 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); |
14677 if (HasFastProperties()) { | 14751 if (HasFastProperties()) { |
14678 int start_index = index; | 14752 int start_index = index; |
14679 int real_size = map()->NumberOfOwnDescriptors(); | 14753 int real_size = map()->NumberOfOwnDescriptors(); |
14680 DescriptorArray* descs = map()->instance_descriptors(); | 14754 DescriptorArray* descs = map()->instance_descriptors(); |
14681 for (int i = 0; i < real_size; i++) { | 14755 for (int i = 0; i < real_size; i++) { |
14682 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 14756 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
14683 !FilterKey(descs->GetKey(i), filter)) { | 14757 !descs->GetKey(i)->FilterKey(filter)) { |
14684 storage->set(index++, descs->GetKey(i)); | 14758 storage->set(index++, descs->GetKey(i)); |
14685 } | 14759 } |
14686 } | 14760 } |
14687 return index - start_index; | 14761 return index - start_index; |
14688 } else if (IsGlobalObject()) { | 14762 } else if (IsGlobalObject()) { |
14689 return global_dictionary()->CopyKeysTo(storage, index, filter, | 14763 return global_dictionary()->CopyKeysTo(storage, index, filter, |
14690 GlobalDictionary::UNSORTED); | 14764 GlobalDictionary::UNSORTED); |
14691 } else { | 14765 } else { |
14692 return property_dictionary()->CopyKeysTo(storage, index, filter, | 14766 return property_dictionary()->CopyKeysTo(storage, index, filter, |
14693 NameDictionary::UNSORTED); | 14767 NameDictionary::UNSORTED); |
(...skipping 14 matching lines...) Expand all Loading... | |
14708 // Compute the number of enumerable elements. | 14782 // Compute the number of enumerable elements. |
14709 return GetOwnElementKeys(NULL, filter); | 14783 return GetOwnElementKeys(NULL, filter); |
14710 } | 14784 } |
14711 | 14785 |
14712 | 14786 |
14713 int JSObject::NumberOfEnumElements() { | 14787 int JSObject::NumberOfEnumElements() { |
14714 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 14788 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
14715 } | 14789 } |
14716 | 14790 |
14717 | 14791 |
14792 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | |
14793 KeyAccumulator* keys, | |
14794 PropertyAttributes filter) { | |
14795 uint32_t string_keys = 0; | |
14796 | |
14797 // If this is a String wrapper, add the string indices first, | |
14798 // as they're guaranteed to precede the elements in numerical order | |
14799 // and ascending order is required by ECMA-262, 6th, 9.1.12. | |
14800 if (object->IsJSValue()) { | |
14801 Object* val = JSValue::cast(*object)->value(); | |
14802 if (val->IsString()) { | |
14803 String* str = String::cast(val); | |
14804 string_keys = str->length(); | |
14805 for (uint32_t i = 0; i < string_keys; i++) { | |
14806 keys->AddKey(i); | |
14807 } | |
14808 } | |
14809 } | |
14810 ElementsAccessor* accessor = object->GetElementsAccessor(); | |
14811 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | |
14812 } | |
14813 | |
14814 | |
14718 int JSObject::GetOwnElementKeys(FixedArray* storage, | 14815 int JSObject::GetOwnElementKeys(FixedArray* storage, |
14719 PropertyAttributes filter) { | 14816 PropertyAttributes filter) { |
14720 int counter = 0; | 14817 int counter = 0; |
14721 | 14818 |
14722 // If this is a String wrapper, add the string indices first, | 14819 // If this is a String wrapper, add the string indices first, |
14723 // as they're guaranteed to preced the elements in numerical order | 14820 // as they're guaranteed to precede the elements in numerical order |
14724 // and ascending order is required by ECMA-262, 6th, 9.1.12. | 14821 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
14725 if (IsJSValue()) { | 14822 if (IsJSValue()) { |
14726 Object* val = JSValue::cast(this)->value(); | 14823 Object* val = JSValue::cast(this)->value(); |
14727 if (val->IsString()) { | 14824 if (val->IsString()) { |
14728 String* str = String::cast(val); | 14825 String* str = String::cast(val); |
14729 if (storage) { | 14826 if (storage) { |
14730 for (int i = 0; i < str->length(); i++) { | 14827 for (int i = 0; i < str->length(); i++) { |
14731 storage->set(counter + i, Smi::FromInt(i)); | 14828 storage->set(counter + i, Smi::FromInt(i)); |
14732 } | 14829 } |
14733 } | 14830 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14838 } | 14935 } |
14839 break; | 14936 break; |
14840 } | 14937 } |
14841 } | 14938 } |
14842 | 14939 |
14843 DCHECK(!storage || storage->length() == counter); | 14940 DCHECK(!storage || storage->length() == counter); |
14844 return counter; | 14941 return counter; |
14845 } | 14942 } |
14846 | 14943 |
14847 | 14944 |
14848 int JSObject::GetEnumElementKeys(FixedArray* storage) { | |
14849 return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM)); | |
14850 } | |
14851 | |
14852 | |
14853 const char* Symbol::PrivateSymbolToName() const { | 14945 const char* Symbol::PrivateSymbolToName() const { |
14854 Heap* heap = GetIsolate()->heap(); | 14946 Heap* heap = GetIsolate()->heap(); |
14855 #define SYMBOL_CHECK_AND_PRINT(name) \ | 14947 #define SYMBOL_CHECK_AND_PRINT(name) \ |
14856 if (this == heap->name()) return #name; | 14948 if (this == heap->name()) return #name; |
14857 PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT) | 14949 PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT) |
14858 #undef SYMBOL_CHECK_AND_PRINT | 14950 #undef SYMBOL_CHECK_AND_PRINT |
14859 return "UNKNOWN"; | 14951 return "UNKNOWN"; |
14860 } | 14952 } |
14861 | 14953 |
14862 | 14954 |
(...skipping 1503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16366 } | 16458 } |
16367 | 16459 |
16368 | 16460 |
16369 template <typename Derived, typename Shape, typename Key> | 16461 template <typename Derived, typename Shape, typename Key> |
16370 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes( | 16462 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes( |
16371 PropertyAttributes filter) { | 16463 PropertyAttributes filter) { |
16372 int capacity = this->Capacity(); | 16464 int capacity = this->Capacity(); |
16373 int result = 0; | 16465 int result = 0; |
16374 for (int i = 0; i < capacity; i++) { | 16466 for (int i = 0; i < capacity; i++) { |
16375 Object* k = this->KeyAt(i); | 16467 Object* k = this->KeyAt(i); |
16376 if (this->IsKey(k) && !FilterKey(k, filter)) { | 16468 if (this->IsKey(k) && !k->FilterKey(filter)) { |
16377 if (this->IsDeleted(i)) continue; | 16469 if (this->IsDeleted(i)) continue; |
16378 PropertyDetails details = this->DetailsAt(i); | 16470 PropertyDetails details = this->DetailsAt(i); |
16379 PropertyAttributes attr = details.attributes(); | 16471 PropertyAttributes attr = details.attributes(); |
16380 if ((attr & filter) == 0) result++; | 16472 if ((attr & filter) == 0) result++; |
16381 } | 16473 } |
16382 } | 16474 } |
16383 return result; | 16475 return result; |
16384 } | 16476 } |
16385 | 16477 |
16386 | 16478 |
16387 template <typename Derived, typename Shape, typename Key> | 16479 template <typename Derived, typename Shape, typename Key> |
16388 bool Dictionary<Derived, Shape, Key>::HasComplexElements() { | 16480 bool Dictionary<Derived, Shape, Key>::HasComplexElements() { |
16389 int capacity = this->Capacity(); | 16481 int capacity = this->Capacity(); |
16390 for (int i = 0; i < capacity; i++) { | 16482 for (int i = 0; i < capacity; i++) { |
16391 Object* k = this->KeyAt(i); | 16483 Object* k = this->KeyAt(i); |
16392 if (this->IsKey(k) && !FilterKey(k, NONE)) { | 16484 if (this->IsKey(k) && !k->FilterKey(NONE)) { |
16393 if (this->IsDeleted(i)) continue; | 16485 if (this->IsDeleted(i)) continue; |
16394 PropertyDetails details = this->DetailsAt(i); | 16486 PropertyDetails details = this->DetailsAt(i); |
16395 if (details.type() == ACCESSOR_CONSTANT) return true; | 16487 if (details.type() == ACCESSOR_CONSTANT) return true; |
16396 PropertyAttributes attr = details.attributes(); | 16488 PropertyAttributes attr = details.attributes(); |
16397 if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true; | 16489 if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true; |
16398 } | 16490 } |
16399 } | 16491 } |
16400 return false; | 16492 return false; |
16401 } | 16493 } |
16402 | 16494 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16441 | 16533 |
16442 template <typename Derived, typename Shape, typename Key> | 16534 template <typename Derived, typename Shape, typename Key> |
16443 int Dictionary<Derived, Shape, Key>::CopyKeysTo( | 16535 int Dictionary<Derived, Shape, Key>::CopyKeysTo( |
16444 FixedArray* storage, int index, PropertyAttributes filter, | 16536 FixedArray* storage, int index, PropertyAttributes filter, |
16445 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 16537 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
16446 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 16538 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
16447 int start_index = index; | 16539 int start_index = index; |
16448 int capacity = this->Capacity(); | 16540 int capacity = this->Capacity(); |
16449 for (int i = 0; i < capacity; i++) { | 16541 for (int i = 0; i < capacity; i++) { |
16450 Object* k = this->KeyAt(i); | 16542 Object* k = this->KeyAt(i); |
16451 if (this->IsKey(k) && !FilterKey(k, filter)) { | 16543 if (this->IsKey(k) && !k->FilterKey(filter)) { |
16452 if (this->IsDeleted(i)) continue; | 16544 if (this->IsDeleted(i)) continue; |
16453 PropertyDetails details = this->DetailsAt(i); | 16545 PropertyDetails details = this->DetailsAt(i); |
16454 PropertyAttributes attr = details.attributes(); | 16546 PropertyAttributes attr = details.attributes(); |
16455 if ((attr & filter) == 0) storage->set(index++, k); | 16547 if ((attr & filter) == 0) storage->set(index++, k); |
16456 } | 16548 } |
16457 } | 16549 } |
16458 if (sort_mode == Dictionary::SORTED) { | 16550 if (sort_mode == Dictionary::SORTED) { |
16459 storage->SortPairs(storage, index); | 16551 storage->SortPairs(storage, index); |
16460 } | 16552 } |
16461 DCHECK(storage->length() >= index); | 16553 DCHECK(storage->length() >= index); |
(...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17666 if (cell->value() != *new_value) { | 17758 if (cell->value() != *new_value) { |
17667 cell->set_value(*new_value); | 17759 cell->set_value(*new_value); |
17668 Isolate* isolate = cell->GetIsolate(); | 17760 Isolate* isolate = cell->GetIsolate(); |
17669 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17761 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17670 isolate, DependentCode::kPropertyCellChangedGroup); | 17762 isolate, DependentCode::kPropertyCellChangedGroup); |
17671 } | 17763 } |
17672 } | 17764 } |
17673 | 17765 |
17674 } // namespace internal | 17766 } // namespace internal |
17675 } // namespace v8 | 17767 } // namespace v8 |
OLD | NEW |