OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include "src/execution.h" | 27 #include "src/execution.h" |
28 #include "src/field-index-inl.h" | 28 #include "src/field-index-inl.h" |
29 #include "src/field-index.h" | 29 #include "src/field-index.h" |
30 #include "src/field-type.h" | 30 #include "src/field-type.h" |
31 #include "src/full-codegen/full-codegen.h" | 31 #include "src/full-codegen/full-codegen.h" |
32 #include "src/ic/ic.h" | 32 #include "src/ic/ic.h" |
33 #include "src/identity-map.h" | 33 #include "src/identity-map.h" |
34 #include "src/interpreter/bytecodes.h" | 34 #include "src/interpreter/bytecodes.h" |
35 #include "src/interpreter/source-position-table.h" | 35 #include "src/interpreter/source-position-table.h" |
36 #include "src/isolate-inl.h" | 36 #include "src/isolate-inl.h" |
37 #include "src/keys.h" | 37 #include "src/key-accumulator.h" |
38 #include "src/list.h" | 38 #include "src/list.h" |
39 #include "src/log.h" | 39 #include "src/log.h" |
40 #include "src/lookup.h" | 40 #include "src/lookup.h" |
41 #include "src/macro-assembler.h" | 41 #include "src/macro-assembler.h" |
42 #include "src/messages.h" | 42 #include "src/messages.h" |
43 #include "src/objects-inl.h" | 43 #include "src/objects-inl.h" |
44 #include "src/objects-body-descriptors-inl.h" | 44 #include "src/objects-body-descriptors-inl.h" |
45 #include "src/profiler/cpu-profiler.h" | 45 #include "src/profiler/cpu-profiler.h" |
46 #include "src/property-descriptor.h" | 46 #include "src/property-descriptor.h" |
47 #include "src/prototype.h" | 47 #include "src/prototype.h" |
(...skipping 8184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8232 if (result->IsPrimitive()) return result; | 8232 if (result->IsPrimitive()) return result; |
8233 } | 8233 } |
8234 } | 8234 } |
8235 THROW_NEW_ERROR(isolate, | 8235 THROW_NEW_ERROR(isolate, |
8236 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), | 8236 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), |
8237 Object); | 8237 Object); |
8238 } | 8238 } |
8239 | 8239 |
8240 | 8240 |
8241 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. | 8241 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. |
8242 bool JSObject::HasEnumerableElements() { | 8242 bool HasEnumerableElements(JSObject* object) { |
8243 // TODO(cbruni): cleanup | |
8244 JSObject* object = this; | |
8245 switch (object->GetElementsKind()) { | 8243 switch (object->GetElementsKind()) { |
8246 case FAST_SMI_ELEMENTS: | 8244 case FAST_SMI_ELEMENTS: |
8247 case FAST_ELEMENTS: | 8245 case FAST_ELEMENTS: |
8248 case FAST_DOUBLE_ELEMENTS: { | 8246 case FAST_DOUBLE_ELEMENTS: { |
8249 int length = object->IsJSArray() | 8247 int length = object->IsJSArray() |
8250 ? Smi::cast(JSArray::cast(object)->length())->value() | 8248 ? Smi::cast(JSArray::cast(object)->length())->value() |
8251 : object->elements()->length(); | 8249 : object->elements()->length(); |
8252 return length > 0; | 8250 return length > 0; |
8253 } | 8251 } |
8254 case FAST_HOLEY_SMI_ELEMENTS: | 8252 case FAST_HOLEY_SMI_ELEMENTS: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8299 return true; | 8297 return true; |
8300 } | 8298 } |
8301 return object->elements()->length() > 0; | 8299 return object->elements()->length() > 0; |
8302 case NO_ELEMENTS: | 8300 case NO_ELEMENTS: |
8303 return false; | 8301 return false; |
8304 } | 8302 } |
8305 UNREACHABLE(); | 8303 UNREACHABLE(); |
8306 return true; | 8304 return true; |
8307 } | 8305 } |
8308 | 8306 |
| 8307 |
8309 // Tests for the fast common case for property enumeration: | 8308 // Tests for the fast common case for property enumeration: |
8310 // - This object and all prototypes has an enum cache (which means that | 8309 // - This object and all prototypes has an enum cache (which means that |
8311 // it is no proxy, has no interceptors and needs no access checks). | 8310 // it is no proxy, has no interceptors and needs no access checks). |
8312 // - This object has no elements. | 8311 // - This object has no elements. |
8313 // - No prototype has enumerable properties/elements. | 8312 // - No prototype has enumerable properties/elements. |
8314 bool JSReceiver::IsSimpleEnum() { | 8313 bool JSReceiver::IsSimpleEnum() { |
8315 for (PrototypeIterator iter(GetIsolate(), this, | 8314 for (PrototypeIterator iter(GetIsolate(), this, |
8316 PrototypeIterator::START_AT_RECEIVER); | 8315 PrototypeIterator::START_AT_RECEIVER); |
8317 !iter.IsAtEnd(); iter.Advance()) { | 8316 !iter.IsAtEnd(); iter.Advance()) { |
8318 if (!iter.GetCurrent()->IsJSObject()) return false; | 8317 if (!iter.GetCurrent()->IsJSObject()) return false; |
8319 JSObject* current = iter.GetCurrent<JSObject>(); | 8318 JSObject* current = iter.GetCurrent<JSObject>(); |
8320 int enum_length = current->map()->EnumLength(); | 8319 int enum_length = current->map()->EnumLength(); |
8321 if (enum_length == kInvalidEnumCacheSentinel) return false; | 8320 if (enum_length == kInvalidEnumCacheSentinel) return false; |
8322 if (current->IsAccessCheckNeeded()) return false; | 8321 if (current->IsAccessCheckNeeded()) return false; |
8323 DCHECK(!current->HasNamedInterceptor()); | 8322 DCHECK(!current->HasNamedInterceptor()); |
8324 DCHECK(!current->HasIndexedInterceptor()); | 8323 DCHECK(!current->HasIndexedInterceptor()); |
8325 if (current->HasEnumerableElements()) return false; | 8324 if (HasEnumerableElements(current)) return false; |
8326 if (current != this && enum_length != 0) return false; | 8325 if (current != this && enum_length != 0) return false; |
8327 } | 8326 } |
8328 return true; | 8327 return true; |
8329 } | 8328 } |
8330 | 8329 |
8331 | 8330 |
8332 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 8331 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
8333 PropertyFilter filter) { | 8332 PropertyFilter filter) { |
8334 int result = 0; | 8333 int result = 0; |
8335 DescriptorArray* descs = instance_descriptors(); | 8334 DescriptorArray* descs = instance_descriptors(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8379 } | 8378 } |
8380 | 8379 |
8381 bool Map::OnlyHasSimpleProperties() { | 8380 bool Map::OnlyHasSimpleProperties() { |
8382 // Wrapped string elements aren't explicitly stored in the elements backing | 8381 // Wrapped string elements aren't explicitly stored in the elements backing |
8383 // store, but are loaded indirectly from the underlying string. | 8382 // store, but are loaded indirectly from the underlying string. |
8384 return !IsStringWrapperElementsKind(elements_kind()) && | 8383 return !IsStringWrapperElementsKind(elements_kind()) && |
8385 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && | 8384 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && |
8386 !has_hidden_prototype() && !is_dictionary_map(); | 8385 !has_hidden_prototype() && !is_dictionary_map(); |
8387 } | 8386 } |
8388 | 8387 |
8389 // static | 8388 namespace { |
8390 Handle<FixedArray> JSObject::GetFastEnumPropertyKeys(Isolate* isolate, | 8389 |
8391 Handle<JSObject> object) { | 8390 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, |
| 8391 Handle<JSObject> object) { |
8392 Handle<Map> map(object->map()); | 8392 Handle<Map> map(object->map()); |
8393 bool cache_enum_length = map->OnlyHasSimpleProperties(); | 8393 bool cache_enum_length = map->OnlyHasSimpleProperties(); |
8394 | 8394 |
8395 Handle<DescriptorArray> descs = | 8395 Handle<DescriptorArray> descs = |
8396 Handle<DescriptorArray>(map->instance_descriptors(), isolate); | 8396 Handle<DescriptorArray>(map->instance_descriptors(), isolate); |
8397 int own_property_count = map->EnumLength(); | 8397 int own_property_count = map->EnumLength(); |
8398 // If the enum length of the given map is set to kInvalidEnumCache, this | 8398 // If the enum length of the given map is set to kInvalidEnumCache, this |
8399 // means that the map itself has never used the present enum cache. The | 8399 // means that the map itself has never used the present enum cache. The |
8400 // first step to using the cache is to set the enum length of the map by | 8400 // first step to using the cache is to set the enum length of the map by |
8401 // counting the number of own descriptors that are ENUMERABLE_STRINGS. | 8401 // counting the number of own descriptors that are ENUMERABLE_STRINGS. |
(...skipping 30 matching lines...) Expand all Loading... |
8432 Handle<FixedArray> storage = | 8432 Handle<FixedArray> storage = |
8433 isolate->factory()->NewFixedArray(own_property_count); | 8433 isolate->factory()->NewFixedArray(own_property_count); |
8434 Handle<FixedArray> indices = | 8434 Handle<FixedArray> indices = |
8435 isolate->factory()->NewFixedArray(own_property_count); | 8435 isolate->factory()->NewFixedArray(own_property_count); |
8436 | 8436 |
8437 int size = map->NumberOfOwnDescriptors(); | 8437 int size = map->NumberOfOwnDescriptors(); |
8438 int index = 0; | 8438 int index = 0; |
8439 | 8439 |
8440 for (int i = 0; i < size; i++) { | 8440 for (int i = 0; i < size; i++) { |
8441 PropertyDetails details = descs->GetDetails(i); | 8441 PropertyDetails details = descs->GetDetails(i); |
8442 if (details.IsDontEnum()) continue; | |
8443 Object* key = descs->GetKey(i); | 8442 Object* key = descs->GetKey(i); |
8444 if (key->IsSymbol()) continue; | 8443 if (details.IsDontEnum() || key->IsSymbol()) continue; |
8445 storage->set(index, key); | 8444 storage->set(index, key); |
8446 if (!indices.is_null()) { | 8445 if (!indices.is_null()) { |
8447 if (details.type() != DATA) { | 8446 if (details.type() != DATA) { |
8448 indices = Handle<FixedArray>(); | 8447 indices = Handle<FixedArray>(); |
8449 } else { | 8448 } else { |
8450 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); | 8449 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); |
8451 int load_by_field_index = field_index.GetLoadByFieldIndex(); | 8450 int load_by_field_index = field_index.GetLoadByFieldIndex(); |
8452 indices->set(index, Smi::FromInt(load_by_field_index)); | 8451 indices->set(index, Smi::FromInt(load_by_field_index)); |
8453 } | 8452 } |
8454 } | 8453 } |
8455 index++; | 8454 index++; |
8456 } | 8455 } |
8457 DCHECK(index == storage->length()); | 8456 DCHECK(index == storage->length()); |
8458 | 8457 |
8459 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); | 8458 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); |
8460 if (cache_enum_length) { | 8459 if (cache_enum_length) { |
8461 map->SetEnumLength(own_property_count); | 8460 map->SetEnumLength(own_property_count); |
8462 } | 8461 } |
8463 return storage; | 8462 return storage; |
8464 } | 8463 } |
8465 | 8464 |
| 8465 } // namespace |
8466 | 8466 |
8467 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) { | 8467 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) { |
8468 Isolate* isolate = object->GetIsolate(); | 8468 Isolate* isolate = object->GetIsolate(); |
8469 if (object->HasFastProperties()) { | 8469 if (object->HasFastProperties()) { |
8470 return GetFastEnumPropertyKeys(isolate, object); | 8470 return GetFastEnumPropertyKeys(isolate, object); |
8471 } else if (object->IsJSGlobalObject()) { | 8471 } else if (object->IsJSGlobalObject()) { |
8472 Handle<GlobalDictionary> dictionary(object->global_dictionary()); | 8472 Handle<GlobalDictionary> dictionary(object->global_dictionary()); |
8473 int length = dictionary->NumberOfEnumElements(); | 8473 int length = dictionary->NumberOfEnumElements(); |
8474 if (length == 0) { | 8474 if (length == 0) { |
8475 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 8475 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
(...skipping 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10673 array = EnsureSpace(array, length + 1); | 10673 array = EnsureSpace(array, length + 1); |
10674 if (mode == kReloadLengthAfterAllocation) { | 10674 if (mode == kReloadLengthAfterAllocation) { |
10675 DCHECK(array->Length() <= length); | 10675 DCHECK(array->Length() <= length); |
10676 length = array->Length(); | 10676 length = array->Length(); |
10677 } | 10677 } |
10678 array->Set(length, *obj); | 10678 array->Set(length, *obj); |
10679 array->SetLength(length + 1); | 10679 array->SetLength(length + 1); |
10680 return array; | 10680 return array; |
10681 } | 10681 } |
10682 | 10682 |
| 10683 |
10683 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, | 10684 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, |
10684 Handle<Object> obj2, AddMode mode) { | 10685 Handle<Object> obj2, AddMode mode) { |
10685 int length = array->Length(); | 10686 int length = array->Length(); |
10686 array = EnsureSpace(array, length + 2); | 10687 array = EnsureSpace(array, length + 2); |
10687 if (mode == kReloadLengthAfterAllocation) { | 10688 if (mode == kReloadLengthAfterAllocation) { |
10688 length = array->Length(); | 10689 length = array->Length(); |
10689 } | 10690 } |
10690 array->Set(length, *obj1); | 10691 array->Set(length, *obj1); |
10691 array->Set(length + 1, *obj2); | 10692 array->Set(length + 1, *obj2); |
10692 array->SetLength(length + 2); | 10693 array->SetLength(length + 2); |
(...skipping 5741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16434 j++ < len) { | 16435 j++ < len) { |
16435 SwapPairs(numbers, i, p); | 16436 SwapPairs(numbers, i, p); |
16436 } | 16437 } |
16437 } | 16438 } |
16438 } else { | 16439 } else { |
16439 HeapSortPairs(this, numbers, len); | 16440 HeapSortPairs(this, numbers, len); |
16440 return; | 16441 return; |
16441 } | 16442 } |
16442 } | 16443 } |
16443 | 16444 |
| 16445 |
16444 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | 16446 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, |
16445 PropertyFilter filter) { | 16447 PropertyFilter filter) { |
16446 if (HasFastProperties()) { | 16448 if (HasFastProperties()) { |
16447 int real_size = map()->NumberOfOwnDescriptors(); | 16449 int real_size = map()->NumberOfOwnDescriptors(); |
16448 Handle<DescriptorArray> descs(map()->instance_descriptors()); | 16450 Handle<DescriptorArray> descs(map()->instance_descriptors()); |
16449 for (int i = 0; i < real_size; i++) { | 16451 for (int i = 0; i < real_size; i++) { |
16450 PropertyDetails details = descs->GetDetails(i); | 16452 PropertyDetails details = descs->GetDetails(i); |
16451 if ((details.attributes() & filter) != 0) continue; | 16453 if ((details.attributes() & filter) != 0) continue; |
16452 if (filter & ONLY_ALL_CAN_READ) { | 16454 if (filter & ONLY_ALL_CAN_READ) { |
16453 if (details.kind() != kAccessor) continue; | 16455 if (details.kind() != kAccessor) continue; |
(...skipping 20 matching lines...) Expand all Loading... |
16474 IsJSArray() | 16476 IsJSArray() |
16475 ? static_cast<uint32_t>( | 16477 ? static_cast<uint32_t>( |
16476 Smi::cast(JSArray::cast(this)->length())->value()) | 16478 Smi::cast(JSArray::cast(this)->length())->value()) |
16477 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 16479 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
16478 if (length == 0) return 0; | 16480 if (length == 0) return 0; |
16479 } | 16481 } |
16480 // Compute the number of enumerable elements. | 16482 // Compute the number of enumerable elements. |
16481 return GetOwnElementKeys(NULL, filter); | 16483 return GetOwnElementKeys(NULL, filter); |
16482 } | 16484 } |
16483 | 16485 |
| 16486 |
16484 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 16487 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
16485 KeyAccumulator* keys, | 16488 KeyAccumulator* keys, |
16486 PropertyFilter filter) { | 16489 PropertyFilter filter) { |
16487 if (filter & SKIP_STRINGS) return; | 16490 if (filter & SKIP_STRINGS) return; |
16488 ElementsAccessor* accessor = object->GetElementsAccessor(); | 16491 ElementsAccessor* accessor = object->GetElementsAccessor(); |
16489 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 16492 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
16490 } | 16493 } |
16491 | 16494 |
16492 | 16495 |
16493 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { | 16496 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { |
(...skipping 1987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18481 if ((attr & filter) != 0) continue; | 18484 if ((attr & filter) != 0) continue; |
18482 storage->set(index++, k); | 18485 storage->set(index++, k); |
18483 } | 18486 } |
18484 if (sort_mode == Dictionary::SORTED) { | 18487 if (sort_mode == Dictionary::SORTED) { |
18485 storage->SortPairs(storage, index); | 18488 storage->SortPairs(storage, index); |
18486 } | 18489 } |
18487 DCHECK(storage->length() >= index); | 18490 DCHECK(storage->length() >= index); |
18488 return index - start_index; | 18491 return index - start_index; |
18489 } | 18492 } |
18490 | 18493 |
| 18494 |
18491 template <typename Derived, typename Shape, typename Key> | 18495 template <typename Derived, typename Shape, typename Key> |
18492 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 18496 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
18493 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 18497 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
18494 PropertyFilter filter) { | 18498 PropertyFilter filter) { |
18495 int capacity = dictionary->Capacity(); | 18499 int capacity = dictionary->Capacity(); |
18496 Handle<FixedArray> array = | 18500 Handle<FixedArray> array = |
18497 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 18501 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
18498 int array_size = 0; | 18502 int array_size = 0; |
18499 | 18503 |
18500 { | 18504 { |
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19767 if (cell->value() != *new_value) { | 19771 if (cell->value() != *new_value) { |
19768 cell->set_value(*new_value); | 19772 cell->set_value(*new_value); |
19769 Isolate* isolate = cell->GetIsolate(); | 19773 Isolate* isolate = cell->GetIsolate(); |
19770 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19774 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19771 isolate, DependentCode::kPropertyCellChangedGroup); | 19775 isolate, DependentCode::kPropertyCellChangedGroup); |
19772 } | 19776 } |
19773 } | 19777 } |
19774 | 19778 |
19775 } // namespace internal | 19779 } // namespace internal |
19776 } // namespace v8 | 19780 } // namespace v8 |
OLD | NEW |