Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/objects.cc

Issue 1397063002: [runtime] Fancify KeyAccumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: nits Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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.
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698