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

Side by Side Diff: src/keys.cc

Issue 2002203002: [api] Add more parameters to Object::GetPropertyNames (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@2016-05-06_keys_fast_path_1995263002
Patch Set: addressing nits Created 4 years, 6 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/keys.h ('k') | src/objects.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/keys.h" 5 #include "src/keys.h"
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/elements.h" 8 #include "src/elements.h"
9 #include "src/factory.h" 9 #include "src/factory.h"
10 #include "src/identity-map.h" 10 #include "src/identity-map.h"
(...skipping 15 matching lines...) Expand all
26 for (int i = 0; i < len; i++) { 26 for (int i = 0; i < len; i++) {
27 Object* e = array->get(i); 27 Object* e = array->get(i);
28 if (!(e->IsName() || e->IsNumber())) return false; 28 if (!(e->IsName() || e->IsNumber())) return false;
29 } 29 }
30 return true; 30 return true;
31 } 31 }
32 32
33 } // namespace 33 } // namespace
34 34
35 MaybeHandle<FixedArray> KeyAccumulator::GetKeys( 35 MaybeHandle<FixedArray> KeyAccumulator::GetKeys(
36 Handle<JSReceiver> object, KeyCollectionType type, PropertyFilter filter, 36 Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
37 GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) { 37 GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) {
38 USE(ContainsOnlyValidKeys); 38 USE(ContainsOnlyValidKeys);
39 Isolate* isolate = object->GetIsolate(); 39 Isolate* isolate = object->GetIsolate();
40 KeyAccumulator accumulator(isolate, type, filter); 40 KeyAccumulator accumulator(isolate, mode, filter);
41 accumulator.set_filter_proxy_keys(filter_proxy_keys); 41 accumulator.set_filter_proxy_keys(filter_proxy_keys);
42 accumulator.set_is_for_in(is_for_in); 42 accumulator.set_is_for_in(is_for_in);
43 MAYBE_RETURN(accumulator.CollectKeys(object, object), 43 MAYBE_RETURN(accumulator.CollectKeys(object, object),
44 MaybeHandle<FixedArray>()); 44 MaybeHandle<FixedArray>());
45 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); 45 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion);
46 DCHECK(ContainsOnlyValidKeys(keys)); 46 DCHECK(ContainsOnlyValidKeys(keys));
47 return keys; 47 return keys;
48 } 48 }
49 49
50 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { 50 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
51 if (keys_.is_null()) { 51 if (keys_.is_null()) {
52 return isolate_->factory()->empty_fixed_array(); 52 return isolate_->factory()->empty_fixed_array();
53 } 53 }
54 if (type_ == OWN_ONLY && 54 if (mode_ == KeyCollectionMode::kOwnOnly &&
55 keys_->map() == isolate_->heap()->fixed_array_map()) { 55 keys_->map() == isolate_->heap()->fixed_array_map()) {
56 return Handle<FixedArray>::cast(keys_); 56 return Handle<FixedArray>::cast(keys_);
57 } 57 }
58 return OrderedHashSet::ConvertToKeysArray(keys(), convert); 58 return OrderedHashSet::ConvertToKeysArray(keys(), convert);
59 } 59 }
60 60
61 void KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { 61 void KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
62 AddKey(handle(key, isolate_), convert); 62 AddKey(handle(key, isolate_), convert);
63 } 63 }
64 64
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 127
128 // Returns "nothing" in case of exception, "true" on success. 128 // Returns "nothing" in case of exception, "true" on success.
129 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, 129 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy,
130 Handle<FixedArray> keys) { 130 Handle<FixedArray> keys) {
131 if (filter_proxy_keys_) { 131 if (filter_proxy_keys_) {
132 DCHECK(!is_for_in_); 132 DCHECK(!is_for_in_);
133 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 133 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
134 isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_), 134 isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_),
135 Nothing<bool>()); 135 Nothing<bool>());
136 } 136 }
137 if (type_ == OWN_ONLY && !is_for_in_) { 137 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) {
138 // If we collect only the keys from a JSProxy do not sort or deduplicate it. 138 // If we collect only the keys from a JSProxy do not sort or deduplicate it.
139 keys_ = keys; 139 keys_ = keys;
140 return Just(true); 140 return Just(true);
141 } 141 }
142 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); 142 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT);
143 return Just(true); 143 return Just(true);
144 } 144 }
145 145
146 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver, 146 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver,
147 Handle<JSReceiver> object) { 147 Handle<JSReceiver> object) {
148 // Proxies have no hidden prototype and we should not trigger the 148 // Proxies have no hidden prototype and we should not trigger the
149 // [[GetPrototypeOf]] trap on the last iteration when using 149 // [[GetPrototypeOf]] trap on the last iteration when using
150 // AdvanceFollowingProxies. 150 // AdvanceFollowingProxies.
151 if (type_ == OWN_ONLY && object->IsJSProxy()) { 151 if (mode_ == KeyCollectionMode::kOwnOnly && object->IsJSProxy()) {
152 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)), 152 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)),
153 Nothing<bool>()); 153 Nothing<bool>());
154 return Just(true); 154 return Just(true);
155 } 155 }
156 156
157 PrototypeIterator::WhereToEnd end = type_ == OWN_ONLY 157 PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly
158 ? PrototypeIterator::END_AT_NON_HIDDEN 158 ? PrototypeIterator::END_AT_NON_HIDDEN
159 : PrototypeIterator::END_AT_NULL; 159 : PrototypeIterator::END_AT_NULL;
160 for (PrototypeIterator iter(isolate_, object, 160 for (PrototypeIterator iter(isolate_, object,
161 PrototypeIterator::START_AT_RECEIVER, end); 161 PrototypeIterator::START_AT_RECEIVER, end);
162 !iter.IsAtEnd();) { 162 !iter.IsAtEnd();) {
163 Handle<JSReceiver> current = 163 Handle<JSReceiver> current =
164 PrototypeIterator::GetCurrent<JSReceiver>(iter); 164 PrototypeIterator::GetCurrent<JSReceiver>(iter);
165 Maybe<bool> result = Just(false); // Dummy initialization. 165 Maybe<bool> result = Just(false); // Dummy initialization.
166 if (current->IsJSProxy()) { 166 if (current->IsJSProxy()) {
167 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current)); 167 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 202 }
203 if (object->map()->EnumLength() != 0) return false; 203 if (object->map()->EnumLength() != 0) return false;
204 DCHECK(object->IsJSObject()); 204 DCHECK(object->IsJSObject());
205 return !JSObject::cast(object)->HasEnumerableElements(); 205 return !JSObject::cast(object)->HasEnumerableElements();
206 } 206 }
207 } // namespace 207 } // namespace
208 208
209 void FastKeyAccumulator::Prepare() { 209 void FastKeyAccumulator::Prepare() {
210 DisallowHeapAllocation no_gc; 210 DisallowHeapAllocation no_gc;
211 // Directly go for the fast path for OWN_ONLY keys. 211 // Directly go for the fast path for OWN_ONLY keys.
212 if (type_ == OWN_ONLY) return; 212 if (mode_ == KeyCollectionMode::kOwnOnly) return;
213 // Fully walk the prototype chain and find the last prototype with keys. 213 // Fully walk the prototype chain and find the last prototype with keys.
214 is_receiver_simple_enum_ = false; 214 is_receiver_simple_enum_ = false;
215 has_empty_prototype_ = true; 215 has_empty_prototype_ = true;
216 JSReceiver* first_non_empty_prototype; 216 JSReceiver* first_non_empty_prototype;
217 for (PrototypeIterator iter(isolate_, *receiver_); !iter.IsAtEnd(); 217 for (PrototypeIterator iter(isolate_, *receiver_); !iter.IsAtEnd();
218 iter.Advance()) { 218 iter.Advance()) {
219 JSReceiver* current = iter.GetCurrent<JSReceiver>(); 219 JSReceiver* current = iter.GetCurrent<JSReceiver>();
220 if (CheckAndInitalizeSimpleEnumCache(current)) continue; 220 if (CheckAndInitalizeSimpleEnumCache(current)) continue;
221 has_empty_prototype_ = false; 221 has_empty_prototype_ = false;
222 first_non_empty_prototype = current; 222 first_non_empty_prototype = current;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeys(GetKeysConversion convert) { 365 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeys(GetKeysConversion convert) {
366 Handle<FixedArray> keys; 366 Handle<FixedArray> keys;
367 if (GetKeysFast(convert).ToHandle(&keys)) { 367 if (GetKeysFast(convert).ToHandle(&keys)) {
368 return keys; 368 return keys;
369 } 369 }
370 return GetKeysSlow(convert); 370 return GetKeysSlow(convert);
371 } 371 }
372 372
373 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast( 373 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
374 GetKeysConversion convert) { 374 GetKeysConversion convert) {
375 bool own_only = has_empty_prototype_ || type_ == OWN_ONLY; 375 bool own_only = has_empty_prototype_ || mode_ == KeyCollectionMode::kOwnOnly;
376 Map* map = receiver_->map(); 376 Map* map = receiver_->map();
377 if (!own_only || !OnlyHasSimpleProperties(map)) { 377 if (!own_only || !OnlyHasSimpleProperties(map)) {
378 return MaybeHandle<FixedArray>(); 378 return MaybeHandle<FixedArray>();
379 } 379 }
380 380
381 // From this point on we are certiain to only collect own keys. 381 // From this point on we are certiain to only collect own keys.
382 DCHECK(receiver_->IsJSObject()); 382 DCHECK(receiver_->IsJSObject());
383 Handle<JSObject> object = Handle<JSObject>::cast(receiver_); 383 Handle<JSObject> object = Handle<JSObject>::cast(receiver_);
384 384
385 // Do not try to use the enum-cache for dict-mode objects. 385 // Do not try to use the enum-cache for dict-mode objects.
(...skipping 15 matching lines...) Expand all
401 return keys; 401 return keys;
402 } 402 }
403 } 403 }
404 // The properties-only case failed because there were probably elements on the 404 // The properties-only case failed because there were probably elements on the
405 // receiver. 405 // receiver.
406 return GetOwnKeysWithElements<true>(isolate_, object, convert); 406 return GetOwnKeysWithElements<true>(isolate_, object, convert);
407 } 407 }
408 408
409 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( 409 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
410 GetKeysConversion convert) { 410 GetKeysConversion convert) {
411 return KeyAccumulator::GetKeys(receiver_, type_, filter_, KEEP_NUMBERS, 411 return KeyAccumulator::GetKeys(receiver_, mode_, filter_,
412 GetKeysConversion::kKeepNumbers,
412 filter_proxy_keys_, is_for_in_); 413 filter_proxy_keys_, is_for_in_);
413 } 414 }
414 415
415 namespace { 416 namespace {
416 417
417 enum IndexedOrNamed { kIndexed, kNamed }; 418 enum IndexedOrNamed { kIndexed, kNamed };
418 419
419 // Returns |true| on success, |nothing| on exception. 420 // Returns |true| on success, |nothing| on exception.
420 template <class Callback, IndexedOrNamed type> 421 template <class Callback, IndexedOrNamed type>
421 Maybe<bool> GetKeysFromInterceptor(Handle<JSReceiver> receiver, 422 Maybe<bool> GetKeysFromInterceptor(Handle<JSReceiver> receiver,
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 530
530 // Returns |true| on success, |false| if prototype walking should be stopped, 531 // Returns |true| on success, |false| if prototype walking should be stopped,
531 // |nothing| if an exception was thrown. 532 // |nothing| if an exception was thrown.
532 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, 533 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver,
533 Handle<JSObject> object) { 534 Handle<JSObject> object) {
534 // Check access rights if required. 535 // Check access rights if required.
535 if (object->IsAccessCheckNeeded() && 536 if (object->IsAccessCheckNeeded() &&
536 !isolate_->MayAccess(handle(isolate_->context()), object)) { 537 !isolate_->MayAccess(handle(isolate_->context()), object)) {
537 // The cross-origin spec says that [[Enumerate]] shall return an empty 538 // The cross-origin spec says that [[Enumerate]] shall return an empty
538 // iterator when it doesn't have access... 539 // iterator when it doesn't have access...
539 if (type_ == INCLUDE_PROTOS) { 540 if (mode_ == KeyCollectionMode::kIncludePrototypes) {
540 return Just(false); 541 return Just(false);
541 } 542 }
542 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. 543 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties.
543 DCHECK_EQ(OWN_ONLY, type_); 544 DCHECK(KeyCollectionMode::kOwnOnly == mode_);
544 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); 545 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ);
545 } 546 }
546 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); 547 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>());
547 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); 548 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>());
548 return Just(true); 549 return Just(true);
549 } 550 }
550 551
551 // static 552 // static
552 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys( 553 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys(
553 Isolate* isolate, Handle<JSObject> object) { 554 Isolate* isolate, Handle<JSObject> object) {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); 730 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>());
730 bool prev_filter_proxy_keys_ = filter_proxy_keys_; 731 bool prev_filter_proxy_keys_ = filter_proxy_keys_;
731 filter_proxy_keys_ = false; 732 filter_proxy_keys_ = false;
732 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); 733 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
733 filter_proxy_keys_ = prev_filter_proxy_keys_; 734 filter_proxy_keys_ = prev_filter_proxy_keys_;
734 return result; 735 return result;
735 } 736 }
736 737
737 } // namespace internal 738 } // namespace internal
738 } // namespace v8 739 } // namespace v8
OLDNEW
« no previous file with comments | « src/keys.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698