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/key-accumulator.h" | 37 #include "src/keys.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 HasEnumerableElements(JSObject* object) { | 8242 bool JSObject::HasEnumerableElements() { |
| 8243 // TODO(cbruni): cleanup |
| 8244 JSObject* object = this; |
8243 switch (object->GetElementsKind()) { | 8245 switch (object->GetElementsKind()) { |
8244 case FAST_SMI_ELEMENTS: | 8246 case FAST_SMI_ELEMENTS: |
8245 case FAST_ELEMENTS: | 8247 case FAST_ELEMENTS: |
8246 case FAST_DOUBLE_ELEMENTS: { | 8248 case FAST_DOUBLE_ELEMENTS: { |
8247 int length = object->IsJSArray() | 8249 int length = object->IsJSArray() |
8248 ? Smi::cast(JSArray::cast(object)->length())->value() | 8250 ? Smi::cast(JSArray::cast(object)->length())->value() |
8249 : object->elements()->length(); | 8251 : object->elements()->length(); |
8250 return length > 0; | 8252 return length > 0; |
8251 } | 8253 } |
8252 case FAST_HOLEY_SMI_ELEMENTS: | 8254 case FAST_HOLEY_SMI_ELEMENTS: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8297 return true; | 8299 return true; |
8298 } | 8300 } |
8299 return object->elements()->length() > 0; | 8301 return object->elements()->length() > 0; |
8300 case NO_ELEMENTS: | 8302 case NO_ELEMENTS: |
8301 return false; | 8303 return false; |
8302 } | 8304 } |
8303 UNREACHABLE(); | 8305 UNREACHABLE(); |
8304 return true; | 8306 return true; |
8305 } | 8307 } |
8306 | 8308 |
8307 | |
8308 // Tests for the fast common case for property enumeration: | 8309 // Tests for the fast common case for property enumeration: |
8309 // - This object and all prototypes has an enum cache (which means that | 8310 // - This object and all prototypes has an enum cache (which means that |
8310 // it is no proxy, has no interceptors and needs no access checks). | 8311 // it is no proxy, has no interceptors and needs no access checks). |
8311 // - This object has no elements. | 8312 // - This object has no elements. |
8312 // - No prototype has enumerable properties/elements. | 8313 // - No prototype has enumerable properties/elements. |
8313 bool JSReceiver::IsSimpleEnum() { | 8314 bool JSReceiver::IsSimpleEnum() { |
8314 for (PrototypeIterator iter(GetIsolate(), this, | 8315 for (PrototypeIterator iter(GetIsolate(), this, |
8315 PrototypeIterator::START_AT_RECEIVER); | 8316 PrototypeIterator::START_AT_RECEIVER); |
8316 !iter.IsAtEnd(); iter.Advance()) { | 8317 !iter.IsAtEnd(); iter.Advance()) { |
8317 if (!iter.GetCurrent()->IsJSObject()) return false; | 8318 if (!iter.GetCurrent()->IsJSObject()) return false; |
8318 JSObject* current = iter.GetCurrent<JSObject>(); | 8319 JSObject* current = iter.GetCurrent<JSObject>(); |
8319 int enum_length = current->map()->EnumLength(); | 8320 int enum_length = current->map()->EnumLength(); |
8320 if (enum_length == kInvalidEnumCacheSentinel) return false; | 8321 if (enum_length == kInvalidEnumCacheSentinel) return false; |
8321 if (current->IsAccessCheckNeeded()) return false; | 8322 if (current->IsAccessCheckNeeded()) return false; |
8322 DCHECK(!current->HasNamedInterceptor()); | 8323 DCHECK(!current->HasNamedInterceptor()); |
8323 DCHECK(!current->HasIndexedInterceptor()); | 8324 DCHECK(!current->HasIndexedInterceptor()); |
8324 if (HasEnumerableElements(current)) return false; | 8325 if (current->HasEnumerableElements()) return false; |
8325 if (current != this && enum_length != 0) return false; | 8326 if (current != this && enum_length != 0) return false; |
8326 } | 8327 } |
8327 return true; | 8328 return true; |
8328 } | 8329 } |
8329 | 8330 |
8330 | 8331 |
8331 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 8332 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
8332 PropertyFilter filter) { | 8333 PropertyFilter filter) { |
8333 int result = 0; | 8334 int result = 0; |
8334 DescriptorArray* descs = instance_descriptors(); | 8335 DescriptorArray* descs = instance_descriptors(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8378 } | 8379 } |
8379 | 8380 |
8380 bool Map::OnlyHasSimpleProperties() { | 8381 bool Map::OnlyHasSimpleProperties() { |
8381 // Wrapped string elements aren't explicitly stored in the elements backing | 8382 // Wrapped string elements aren't explicitly stored in the elements backing |
8382 // store, but are loaded indirectly from the underlying string. | 8383 // store, but are loaded indirectly from the underlying string. |
8383 return !IsStringWrapperElementsKind(elements_kind()) && | 8384 return !IsStringWrapperElementsKind(elements_kind()) && |
8384 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && | 8385 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && |
8385 !has_hidden_prototype() && !is_dictionary_map(); | 8386 !has_hidden_prototype() && !is_dictionary_map(); |
8386 } | 8387 } |
8387 | 8388 |
8388 namespace { | 8389 // static |
8389 | 8390 Handle<FixedArray> JSObject::GetFastEnumPropertyKeys(Isolate* isolate, |
8390 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, | 8391 Handle<JSObject> object) { |
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; |
8442 Object* key = descs->GetKey(i); | 8443 Object* key = descs->GetKey(i); |
8443 if (details.IsDontEnum() || key->IsSymbol()) continue; | 8444 if (key->IsSymbol()) continue; |
8444 storage->set(index, key); | 8445 storage->set(index, key); |
8445 if (!indices.is_null()) { | 8446 if (!indices.is_null()) { |
8446 if (details.type() != DATA) { | 8447 if (details.type() != DATA) { |
8447 indices = Handle<FixedArray>(); | 8448 indices = Handle<FixedArray>(); |
8448 } else { | 8449 } else { |
8449 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); | 8450 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); |
8450 int load_by_field_index = field_index.GetLoadByFieldIndex(); | 8451 int load_by_field_index = field_index.GetLoadByFieldIndex(); |
8451 indices->set(index, Smi::FromInt(load_by_field_index)); | 8452 indices->set(index, Smi::FromInt(load_by_field_index)); |
8452 } | 8453 } |
8453 } | 8454 } |
8454 index++; | 8455 index++; |
8455 } | 8456 } |
8456 DCHECK(index == storage->length()); | 8457 DCHECK(index == storage->length()); |
8457 | 8458 |
8458 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); | 8459 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); |
8459 if (cache_enum_length) { | 8460 if (cache_enum_length) { |
8460 map->SetEnumLength(own_property_count); | 8461 map->SetEnumLength(own_property_count); |
8461 } | 8462 } |
8462 return storage; | 8463 return storage; |
8463 } | 8464 } |
8464 | 8465 |
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 | |
10684 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, | 10683 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, |
10685 Handle<Object> obj2, AddMode mode) { | 10684 Handle<Object> obj2, AddMode mode) { |
10686 int length = array->Length(); | 10685 int length = array->Length(); |
10687 array = EnsureSpace(array, length + 2); | 10686 array = EnsureSpace(array, length + 2); |
10688 if (mode == kReloadLengthAfterAllocation) { | 10687 if (mode == kReloadLengthAfterAllocation) { |
10689 length = array->Length(); | 10688 length = array->Length(); |
10690 } | 10689 } |
10691 array->Set(length, *obj1); | 10690 array->Set(length, *obj1); |
10692 array->Set(length + 1, *obj2); | 10691 array->Set(length + 1, *obj2); |
10693 array->SetLength(length + 2); | 10692 array->SetLength(length + 2); |
(...skipping 5741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16435 j++ < len) { | 16434 j++ < len) { |
16436 SwapPairs(numbers, i, p); | 16435 SwapPairs(numbers, i, p); |
16437 } | 16436 } |
16438 } | 16437 } |
16439 } else { | 16438 } else { |
16440 HeapSortPairs(this, numbers, len); | 16439 HeapSortPairs(this, numbers, len); |
16441 return; | 16440 return; |
16442 } | 16441 } |
16443 } | 16442 } |
16444 | 16443 |
16445 | |
16446 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | 16444 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, |
16447 PropertyFilter filter) { | 16445 PropertyFilter filter) { |
16448 if (HasFastProperties()) { | 16446 if (HasFastProperties()) { |
16449 int real_size = map()->NumberOfOwnDescriptors(); | 16447 int real_size = map()->NumberOfOwnDescriptors(); |
16450 Handle<DescriptorArray> descs(map()->instance_descriptors()); | 16448 Handle<DescriptorArray> descs(map()->instance_descriptors()); |
16451 for (int i = 0; i < real_size; i++) { | 16449 for (int i = 0; i < real_size; i++) { |
16452 PropertyDetails details = descs->GetDetails(i); | 16450 PropertyDetails details = descs->GetDetails(i); |
16453 if ((details.attributes() & filter) != 0) continue; | 16451 if ((details.attributes() & filter) != 0) continue; |
16454 if (filter & ONLY_ALL_CAN_READ) { | 16452 if (filter & ONLY_ALL_CAN_READ) { |
16455 if (details.kind() != kAccessor) continue; | 16453 if (details.kind() != kAccessor) continue; |
(...skipping 20 matching lines...) Expand all Loading... |
16476 IsJSArray() | 16474 IsJSArray() |
16477 ? static_cast<uint32_t>( | 16475 ? static_cast<uint32_t>( |
16478 Smi::cast(JSArray::cast(this)->length())->value()) | 16476 Smi::cast(JSArray::cast(this)->length())->value()) |
16479 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 16477 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
16480 if (length == 0) return 0; | 16478 if (length == 0) return 0; |
16481 } | 16479 } |
16482 // Compute the number of enumerable elements. | 16480 // Compute the number of enumerable elements. |
16483 return GetOwnElementKeys(NULL, filter); | 16481 return GetOwnElementKeys(NULL, filter); |
16484 } | 16482 } |
16485 | 16483 |
16486 | |
16487 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 16484 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
16488 KeyAccumulator* keys, | 16485 KeyAccumulator* keys, |
16489 PropertyFilter filter) { | 16486 PropertyFilter filter) { |
16490 if (filter & SKIP_STRINGS) return; | 16487 if (filter & SKIP_STRINGS) return; |
16491 ElementsAccessor* accessor = object->GetElementsAccessor(); | 16488 ElementsAccessor* accessor = object->GetElementsAccessor(); |
16492 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 16489 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
16493 } | 16490 } |
16494 | 16491 |
16495 | 16492 |
16496 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { | 16493 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { |
(...skipping 1987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18484 if ((attr & filter) != 0) continue; | 18481 if ((attr & filter) != 0) continue; |
18485 storage->set(index++, k); | 18482 storage->set(index++, k); |
18486 } | 18483 } |
18487 if (sort_mode == Dictionary::SORTED) { | 18484 if (sort_mode == Dictionary::SORTED) { |
18488 storage->SortPairs(storage, index); | 18485 storage->SortPairs(storage, index); |
18489 } | 18486 } |
18490 DCHECK(storage->length() >= index); | 18487 DCHECK(storage->length() >= index); |
18491 return index - start_index; | 18488 return index - start_index; |
18492 } | 18489 } |
18493 | 18490 |
18494 | |
18495 template <typename Derived, typename Shape, typename Key> | 18491 template <typename Derived, typename Shape, typename Key> |
18496 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 18492 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
18497 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 18493 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
18498 PropertyFilter filter) { | 18494 PropertyFilter filter) { |
18499 int capacity = dictionary->Capacity(); | 18495 int capacity = dictionary->Capacity(); |
18500 Handle<FixedArray> array = | 18496 Handle<FixedArray> array = |
18501 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 18497 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
18502 int array_size = 0; | 18498 int array_size = 0; |
18503 | 18499 |
18504 { | 18500 { |
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19771 if (cell->value() != *new_value) { | 19767 if (cell->value() != *new_value) { |
19772 cell->set_value(*new_value); | 19768 cell->set_value(*new_value); |
19773 Isolate* isolate = cell->GetIsolate(); | 19769 Isolate* isolate = cell->GetIsolate(); |
19774 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19770 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19775 isolate, DependentCode::kPropertyCellChangedGroup); | 19771 isolate, DependentCode::kPropertyCellChangedGroup); |
19776 } | 19772 } |
19777 } | 19773 } |
19778 | 19774 |
19779 } // namespace internal | 19775 } // namespace internal |
19780 } // namespace v8 | 19776 } // namespace v8 |
OLD | NEW |