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

Side by Side Diff: src/keys.cc

Issue 2853393002: [builtins] Migrate Object.keys to CodeStubAssembler builtin. (Closed)
Patch Set: Properly handle the empty case. Created 3 years, 7 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
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 29 matching lines...) Expand all
40 FastKeyAccumulator accumulator(isolate, object, mode, filter); 40 FastKeyAccumulator accumulator(isolate, object, mode, filter);
41 accumulator.set_is_for_in(is_for_in); 41 accumulator.set_is_for_in(is_for_in);
42 return accumulator.GetKeys(keys_conversion); 42 return accumulator.GetKeys(keys_conversion);
43 } 43 }
44 44
45 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { 45 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
46 if (keys_.is_null()) { 46 if (keys_.is_null()) {
47 return isolate_->factory()->empty_fixed_array(); 47 return isolate_->factory()->empty_fixed_array();
48 } 48 }
49 if (mode_ == KeyCollectionMode::kOwnOnly && 49 if (mode_ == KeyCollectionMode::kOwnOnly &&
50 keys_->map() == isolate_->heap()->fixed_array_map()) { 50 (keys_->map() == isolate_->heap()->fixed_array_map() ||
51 keys_->map() == isolate_->heap()->fixed_cow_array_map())) {
51 return Handle<FixedArray>::cast(keys_); 52 return Handle<FixedArray>::cast(keys_);
52 } 53 }
53 USE(ContainsOnlyValidKeys); 54 USE(ContainsOnlyValidKeys);
54 Handle<FixedArray> result = 55 Handle<FixedArray> result =
55 OrderedHashSet::ConvertToKeysArray(keys(), convert); 56 OrderedHashSet::ConvertToKeysArray(keys(), convert);
56 DCHECK(ContainsOnlyValidKeys(result)); 57 DCHECK(ContainsOnlyValidKeys(result));
57 return result; 58 return result;
58 } 59 }
59 60
60 void KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { 61 void KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 if (has_empty_prototype_) { 257 if (has_empty_prototype_) {
257 is_receiver_simple_enum_ = 258 is_receiver_simple_enum_ =
258 receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel && 259 receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel &&
259 !JSObject::cast(*receiver_)->HasEnumerableElements(); 260 !JSObject::cast(*receiver_)->HasEnumerableElements();
260 } else if (last_prototype != nullptr) { 261 } else if (last_prototype != nullptr) {
261 last_non_empty_prototype_ = handle(last_prototype, isolate_); 262 last_non_empty_prototype_ = handle(last_prototype, isolate_);
262 } 263 }
263 } 264 }
264 265
265 namespace { 266 namespace {
266 static Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate, 267
267 Handle<FixedArray> array, 268 Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate,
268 int length) { 269 Handle<FixedArray> array, int length) {
269 DCHECK_LE(length, array->length()); 270 DCHECK_LE(length, array->length());
270 if (array->length() == length) return array; 271 if (array->length() == length) return array;
271 return isolate->factory()->CopyFixedArrayUpTo(array, length); 272 return isolate->factory()->CopyFixedArrayUpTo(array, length);
272 } 273 }
273 274
274 // Initializes and directly returns the enume cache. Users of this function 275 // Initializes and directly returns the enume cache. Users of this function
275 // have to make sure to never directly leak the enum cache. 276 // have to make sure to never directly leak the enum cache.
276 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, 277 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
277 Handle<JSObject> object) { 278 Handle<JSObject> object) {
278 Handle<Map> map(object->map()); 279 Handle<Map> map(object->map());
(...skipping 29 matching lines...) Expand all
308 } 309 }
309 310
310 if (descs->IsEmpty()) { 311 if (descs->IsEmpty()) {
311 isolate->counters()->enum_cache_hits()->Increment(); 312 isolate->counters()->enum_cache_hits()->Increment();
312 if (cache_enum_length) map->SetEnumLength(0); 313 if (cache_enum_length) map->SetEnumLength(0);
313 return isolate->factory()->empty_fixed_array(); 314 return isolate->factory()->empty_fixed_array();
314 } 315 }
315 316
316 isolate->counters()->enum_cache_misses()->Increment(); 317 isolate->counters()->enum_cache_misses()->Increment();
317 318
318 Handle<FixedArray> storage = 319 Handle<FixedArray> storage = isolate->factory()->empty_fixed_array();
319 isolate->factory()->NewFixedArray(own_property_count); 320 Handle<FixedArray> indices = isolate->factory()->empty_fixed_array();
320 Handle<FixedArray> indices = 321 if (own_property_count != 0) {
321 isolate->factory()->NewFixedArray(own_property_count); 322 storage = isolate->factory()->NewFixedArray(own_property_count);
323 indices = isolate->factory()->NewFixedArray(own_property_count);
322 324
323 int size = map->NumberOfOwnDescriptors(); 325 int size = map->NumberOfOwnDescriptors();
324 int index = 0; 326 int index = 0;
325 327
326 for (int i = 0; i < size; i++) { 328 for (int i = 0; i < size; i++) {
327 PropertyDetails details = descs->GetDetails(i); 329 PropertyDetails details = descs->GetDetails(i);
328 if (details.IsDontEnum()) continue; 330 if (details.IsDontEnum()) continue;
329 Object* key = descs->GetKey(i); 331 Object* key = descs->GetKey(i);
330 if (key->IsSymbol()) continue; 332 if (key->IsSymbol()) continue;
331 storage->set(index, key); 333 storage->set(index, key);
332 if (!indices.is_null()) { 334 if (!indices.is_null()) {
333 if (details.location() == kField) { 335 if (details.location() == kField) {
334 DCHECK_EQ(kData, details.kind()); 336 DCHECK_EQ(kData, details.kind());
335 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); 337 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
336 int load_by_field_index = field_index.GetLoadByFieldIndex(); 338 int load_by_field_index = field_index.GetLoadByFieldIndex();
337 indices->set(index, Smi::FromInt(load_by_field_index)); 339 indices->set(index, Smi::FromInt(load_by_field_index));
338 } else { 340 } else {
339 indices = Handle<FixedArray>(); 341 indices = Handle<FixedArray>();
342 }
340 } 343 }
344 index++;
341 } 345 }
342 index++; 346 DCHECK_EQ(index, storage->length());
347
348 // Mark the {storage} as copy-on-write, so we can use this
349 // as JSArray elements backing store directly w/o copying.
350 storage->set_map(isolate->heap()->fixed_cow_array_map());
343 } 351 }
344 DCHECK(index == storage->length());
345 352
346 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); 353 DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
347 if (cache_enum_length) { 354 if (cache_enum_length) {
348 map->SetEnumLength(own_property_count); 355 map->SetEnumLength(own_property_count);
349 } 356 }
350 return storage; 357 return storage;
351 } 358 }
352 359
353 template <bool fast_properties> 360 template <bool fast_properties>
354 MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, 361 MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 // Assume that there are elements. 442 // Assume that there are elements.
436 return MaybeHandle<FixedArray>(); 443 return MaybeHandle<FixedArray>();
437 } 444 }
438 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 445 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
439 if (number_of_own_descriptors == 0) { 446 if (number_of_own_descriptors == 0) {
440 map->SetEnumLength(0); 447 map->SetEnumLength(0);
441 return isolate_->factory()->empty_fixed_array(); 448 return isolate_->factory()->empty_fixed_array();
442 } 449 }
443 // We have no elements but possibly enumerable property keys, hence we can 450 // We have no elements but possibly enumerable property keys, hence we can
444 // directly initialize the enum cache. 451 // directly initialize the enum cache.
445 Handle<FixedArray> keys = GetFastEnumPropertyKeys(isolate_, object); 452 return GetFastEnumPropertyKeys(isolate_, object);
446 if (is_for_in_) return keys;
447 // Do not leak the enum cache as it might end up as an elements backing store.
448 return isolate_->factory()->CopyFixedArray(keys);
449 } 453 }
450 454
451 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( 455 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
452 GetKeysConversion keys_conversion) { 456 GetKeysConversion keys_conversion) {
453 KeyAccumulator accumulator(isolate_, mode_, filter_); 457 KeyAccumulator accumulator(isolate_, mode_, filter_);
454 accumulator.set_is_for_in(is_for_in_); 458 accumulator.set_is_for_in(is_for_in_);
455 accumulator.set_last_non_empty_prototype(last_non_empty_prototype_); 459 accumulator.set_last_non_empty_prototype(last_non_empty_prototype_);
456 460
457 MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_), 461 MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_),
458 MaybeHandle<FixedArray>()); 462 MaybeHandle<FixedArray>());
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 isolate_, keys, 887 isolate_, keys,
884 KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_, 888 KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_,
885 GetKeysConversion::kConvertToString, is_for_in_), 889 GetKeysConversion::kConvertToString, is_for_in_),
886 Nothing<bool>()); 890 Nothing<bool>());
887 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); 891 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
888 return result; 892 return result;
889 } 893 }
890 894
891 } // namespace internal 895 } // namespace internal
892 } // namespace v8 896 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.cc ('k') | src/runtime/runtime.h » ('j') | test/mjsunit/object-keys.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698