OLD | NEW |
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/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 7983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7994 Object); | 7994 Object); |
7995 if (result->IsPrimitive()) return result; | 7995 if (result->IsPrimitive()) return result; |
7996 } | 7996 } |
7997 } | 7997 } |
7998 THROW_NEW_ERROR(isolate, | 7998 THROW_NEW_ERROR(isolate, |
7999 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), | 7999 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), |
8000 Object); | 8000 Object); |
8001 } | 8001 } |
8002 | 8002 |
8003 | 8003 |
| 8004 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. |
| 8005 bool HasEnumerableElements(JSObject* object) { |
| 8006 if (object->IsJSValue()) { |
| 8007 Object* value = JSValue::cast(object)->value(); |
| 8008 if (value->IsString()) { |
| 8009 if (String::cast(value)->length() > 0) return true; |
| 8010 } |
| 8011 } |
| 8012 switch (object->GetElementsKind()) { |
| 8013 case FAST_SMI_ELEMENTS: |
| 8014 case FAST_ELEMENTS: |
| 8015 case FAST_DOUBLE_ELEMENTS: { |
| 8016 int length = object->IsJSArray() |
| 8017 ? Smi::cast(JSArray::cast(object)->length())->value() |
| 8018 : object->elements()->length(); |
| 8019 return length > 0; |
| 8020 } |
| 8021 case FAST_HOLEY_SMI_ELEMENTS: |
| 8022 case FAST_HOLEY_ELEMENTS: { |
| 8023 FixedArray* elements = FixedArray::cast(object->elements()); |
| 8024 int length = object->IsJSArray() |
| 8025 ? Smi::cast(JSArray::cast(object)->length())->value() |
| 8026 : elements->length(); |
| 8027 for (int i = 0; i < length; i++) { |
| 8028 if (!elements->is_the_hole(i)) return true; |
| 8029 } |
| 8030 return false; |
| 8031 } |
| 8032 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 8033 FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements()); |
| 8034 DCHECK(object->IsJSArray()); |
| 8035 int length = Smi::cast(JSArray::cast(object)->length())->value(); |
| 8036 for (int i = 0; i < length; i++) { |
| 8037 if (!elements->is_the_hole(i)) return true; |
| 8038 } |
| 8039 return false; |
| 8040 } |
| 8041 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 8042 case TYPE##_ELEMENTS: |
| 8043 |
| 8044 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 8045 #undef TYPED_ARRAY_CASE |
| 8046 { |
| 8047 int length = object->elements()->length(); |
| 8048 return length > 0; |
| 8049 } |
| 8050 case DICTIONARY_ELEMENTS: { |
| 8051 SeededNumberDictionary* elements = |
| 8052 SeededNumberDictionary::cast(object->elements()); |
| 8053 return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0; |
| 8054 } |
| 8055 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8056 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8057 // We're approximating non-empty arguments objects here. |
| 8058 return true; |
| 8059 } |
| 8060 UNREACHABLE(); |
| 8061 return true; |
| 8062 } |
| 8063 |
| 8064 |
8004 // Tests for the fast common case for property enumeration: | 8065 // Tests for the fast common case for property enumeration: |
8005 // - This object and all prototypes has an enum cache (which means that | 8066 // - This object and all prototypes has an enum cache (which means that |
8006 // it is no proxy, has no interceptors and needs no access checks). | 8067 // it is no proxy, has no interceptors and needs no access checks). |
8007 // - This object has no elements. | 8068 // - This object has no elements. |
8008 // - No prototype has enumerable properties/elements. | 8069 // - No prototype has enumerable properties/elements. |
8009 bool JSReceiver::IsSimpleEnum() { | 8070 bool JSReceiver::IsSimpleEnum() { |
8010 for (PrototypeIterator iter(GetIsolate(), this, | 8071 for (PrototypeIterator iter(GetIsolate(), this, |
8011 PrototypeIterator::START_AT_RECEIVER); | 8072 PrototypeIterator::START_AT_RECEIVER); |
8012 !iter.IsAtEnd(); iter.Advance()) { | 8073 !iter.IsAtEnd(); iter.Advance()) { |
8013 if (!iter.GetCurrent()->IsJSObject()) return false; | 8074 if (!iter.GetCurrent()->IsJSObject()) return false; |
8014 JSObject* current = iter.GetCurrent<JSObject>(); | 8075 JSObject* current = iter.GetCurrent<JSObject>(); |
8015 int enum_length = current->map()->EnumLength(); | 8076 int enum_length = current->map()->EnumLength(); |
8016 if (enum_length == kInvalidEnumCacheSentinel) return false; | 8077 if (enum_length == kInvalidEnumCacheSentinel) return false; |
8017 if (current->IsAccessCheckNeeded()) return false; | 8078 if (current->IsAccessCheckNeeded()) return false; |
8018 DCHECK(!current->HasNamedInterceptor()); | 8079 DCHECK(!current->HasNamedInterceptor()); |
8019 DCHECK(!current->HasIndexedInterceptor()); | 8080 DCHECK(!current->HasIndexedInterceptor()); |
8020 if (current->NumberOfEnumElements() > 0) return false; | 8081 if (HasEnumerableElements(current)) return false; |
8021 if (current != this && enum_length != 0) return false; | 8082 if (current != this && enum_length != 0) return false; |
8022 } | 8083 } |
8023 return true; | 8084 return true; |
8024 } | 8085 } |
8025 | 8086 |
8026 | 8087 |
8027 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 8088 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
8028 PropertyFilter filter) { | 8089 PropertyFilter filter) { |
8029 int result = 0; | 8090 int result = 0; |
8030 DescriptorArray* descs = instance_descriptors(); | 8091 DescriptorArray* descs = instance_descriptors(); |
(...skipping 7936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15967 ? static_cast<uint32_t>( | 16028 ? static_cast<uint32_t>( |
15968 Smi::cast(JSArray::cast(this)->length())->value()) | 16029 Smi::cast(JSArray::cast(this)->length())->value()) |
15969 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 16030 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
15970 if (length == 0) return 0; | 16031 if (length == 0) return 0; |
15971 } | 16032 } |
15972 // Compute the number of enumerable elements. | 16033 // Compute the number of enumerable elements. |
15973 return GetOwnElementKeys(NULL, filter); | 16034 return GetOwnElementKeys(NULL, filter); |
15974 } | 16035 } |
15975 | 16036 |
15976 | 16037 |
15977 int JSObject::NumberOfEnumElements() { | |
15978 return NumberOfOwnElements(ONLY_ENUMERABLE); | |
15979 } | |
15980 | |
15981 | |
15982 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 16038 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
15983 KeyAccumulator* keys, | 16039 KeyAccumulator* keys, |
15984 PropertyFilter filter) { | 16040 PropertyFilter filter) { |
15985 if (filter & SKIP_STRINGS) return; | 16041 if (filter & SKIP_STRINGS) return; |
15986 uint32_t string_keys = 0; | 16042 uint32_t string_keys = 0; |
15987 | 16043 |
15988 // If this is a String wrapper, add the string indices first, | 16044 // If this is a String wrapper, add the string indices first, |
15989 // as they're guaranteed to precede the elements in numerical order | 16045 // as they're guaranteed to precede the elements in numerical order |
15990 // and ascending order is required by ECMA-262, 6th, 9.1.12. | 16046 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
15991 if (object->IsJSValue()) { | 16047 if (object->IsJSValue()) { |
(...skipping 3181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19173 if (cell->value() != *new_value) { | 19229 if (cell->value() != *new_value) { |
19174 cell->set_value(*new_value); | 19230 cell->set_value(*new_value); |
19175 Isolate* isolate = cell->GetIsolate(); | 19231 Isolate* isolate = cell->GetIsolate(); |
19176 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19232 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19177 isolate, DependentCode::kPropertyCellChangedGroup); | 19233 isolate, DependentCode::kPropertyCellChangedGroup); |
19178 } | 19234 } |
19179 } | 19235 } |
19180 | 19236 |
19181 } // namespace internal | 19237 } // namespace internal |
19182 } // namespace v8 | 19238 } // namespace v8 |
OLD | NEW |