| 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 |