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

Side by Side Diff: src/objects.cc

Issue 1612323003: Introduce {FAST,SLOW}_STRING_WRAPPER_ELEMENTS (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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 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 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 Handle<JSObject> result = 1052 Handle<JSObject> result =
1053 isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site); 1053 isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
1054 isolate->counters()->constructed_objects()->Increment(); 1054 isolate->counters()->constructed_objects()->Increment();
1055 isolate->counters()->constructed_objects_runtime()->Increment(); 1055 isolate->counters()->constructed_objects_runtime()->Increment();
1056 return result; 1056 return result;
1057 } 1057 }
1058 1058
1059 1059
1060 Handle<FixedArray> JSObject::EnsureWritableFastElements( 1060 Handle<FixedArray> JSObject::EnsureWritableFastElements(
1061 Handle<JSObject> object) { 1061 Handle<JSObject> object) {
1062 DCHECK(object->HasFastSmiOrObjectElements()); 1062 DCHECK(object->HasFastSmiOrObjectElements() ||
1063 object->HasFastStringWrapperElements());
1063 Isolate* isolate = object->GetIsolate(); 1064 Isolate* isolate = object->GetIsolate();
1064 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); 1065 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
1065 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; 1066 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
1066 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( 1067 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
1067 elems, isolate->factory()->fixed_array_map()); 1068 elems, isolate->factory()->fixed_array_map());
1068 object->set_elements(*writable_elems); 1069 object->set_elements(*writable_elems);
1069 isolate->counters()->cow_arrays_converted()->Increment(); 1070 isolate->counters()->cow_arrays_converted()->Increment();
1070 return writable_elems; 1071 return writable_elems;
1071 } 1072 }
1072 1073
(...skipping 4793 matching lines...) Expand 10 before | Expand all | Expand 10 after
5866 FixedArray* parameter_map = FixedArray::cast(*elements); 5867 FixedArray* parameter_map = FixedArray::cast(*elements);
5867 elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate); 5868 elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
5868 } 5869 }
5869 5870
5870 if (elements->IsDictionary()) { 5871 if (elements->IsDictionary()) {
5871 return Handle<SeededNumberDictionary>::cast(elements); 5872 return Handle<SeededNumberDictionary>::cast(elements);
5872 } 5873 }
5873 5874
5874 DCHECK(object->HasFastSmiOrObjectElements() || 5875 DCHECK(object->HasFastSmiOrObjectElements() ||
5875 object->HasFastDoubleElements() || 5876 object->HasFastDoubleElements() ||
5876 object->HasFastArgumentsElements()); 5877 object->HasFastArgumentsElements() ||
5878 object->HasFastStringWrapperElements());
5877 5879
5878 Handle<SeededNumberDictionary> dictionary = 5880 Handle<SeededNumberDictionary> dictionary =
5879 GetNormalizedElementDictionary(object, elements); 5881 GetNormalizedElementDictionary(object, elements);
5880 5882
5881 // Switch to using the dictionary as the backing storage for elements. 5883 // Switch to using the dictionary as the backing storage for elements.
5882 ElementsKind target_kind = 5884 ElementsKind target_kind = is_arguments
5883 is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS; 5885 ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
5886 : object->HasFastStringWrapperElements()
5887 ? SLOW_STRING_WRAPPER_ELEMENTS
5888 : DICTIONARY_ELEMENTS;
5884 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind); 5889 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
5885 // Set the new map first to satify the elements type assert in set_elements(). 5890 // Set the new map first to satify the elements type assert in set_elements().
5886 JSObject::MigrateToMap(object, new_map); 5891 JSObject::MigrateToMap(object, new_map);
5887 5892
5888 if (is_arguments) { 5893 if (is_arguments) {
5889 FixedArray::cast(object->elements())->set(1, *dictionary); 5894 FixedArray::cast(object->elements())->set(1, *dictionary);
5890 } else { 5895 } else {
5891 object->set_elements(*dictionary); 5896 object->set_elements(*dictionary);
5892 } 5897 }
5893 5898
5894 isolate->counters()->elements_to_dictionary()->Increment(); 5899 isolate->counters()->elements_to_dictionary()->Increment();
5895 5900
5896 #ifdef DEBUG 5901 #ifdef DEBUG
5897 if (FLAG_trace_normalization) { 5902 if (FLAG_trace_normalization) {
5898 OFStream os(stdout); 5903 OFStream os(stdout);
5899 os << "Object elements have been normalized:\n"; 5904 os << "Object elements have been normalized:\n";
5900 object->Print(os); 5905 object->Print(os);
5901 } 5906 }
5902 #endif 5907 #endif
5903 5908
5904 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); 5909 DCHECK(object->HasDictionaryElements() ||
5910 object->HasSlowArgumentsElements() ||
5911 object->HasSlowStringWrapperElements());
5905 return dictionary; 5912 return dictionary;
5906 } 5913 }
5907 5914
5908 5915
5909 static Smi* GenerateIdentityHash(Isolate* isolate) { 5916 static Smi* GenerateIdentityHash(Isolate* isolate) {
5910 int hash_value; 5917 int hash_value;
5911 int attempts = 0; 5918 int attempts = 0;
5912 do { 5919 do {
5913 // Generate a random 32-bit hash value but limit range to fit 5920 // Generate a random 32-bit hash value but limit range to fit
5914 // within a smi. 5921 // within a smi.
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after
7397 } 7404 }
7398 } 7405 }
7399 // 18. Return resultDesc. 7406 // 18. Return resultDesc.
7400 return Just(true); 7407 return Just(true);
7401 } 7408 }
7402 7409
7403 7410
7404 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, 7411 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
7405 ElementsKind kind, 7412 ElementsKind kind,
7406 Object* object) { 7413 Object* object) {
7407 DCHECK(IsFastObjectElementsKind(kind) || 7414 if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
7408 kind == DICTIONARY_ELEMENTS);
7409 if (IsFastObjectElementsKind(kind)) {
7410 int length = IsJSArray() 7415 int length = IsJSArray()
7411 ? Smi::cast(JSArray::cast(this)->length())->value() 7416 ? Smi::cast(JSArray::cast(this)->length())->value()
7412 : elements->length(); 7417 : elements->length();
7413 for (int i = 0; i < length; ++i) { 7418 for (int i = 0; i < length; ++i) {
7414 Object* element = elements->get(i); 7419 Object* element = elements->get(i);
7415 if (!element->IsTheHole() && element == object) return true; 7420 if (!element->IsTheHole() && element == object) return true;
7416 } 7421 }
7417 } else { 7422 } else {
7423 DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
7418 Object* key = 7424 Object* key =
7419 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); 7425 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
7420 if (!key->IsUndefined()) return true; 7426 if (!key->IsUndefined()) return true;
7421 } 7427 }
7422 return false; 7428 return false;
7423 } 7429 }
7424 7430
7425 7431
7426 // Check whether this object references another object. 7432 // Check whether this object references another object.
7427 bool JSObject::ReferencesObject(Object* obj) { 7433 bool JSObject::ReferencesObject(Object* obj) {
(...skipping 30 matching lines...) Expand all
7458 #undef TYPED_ARRAY_CASE 7464 #undef TYPED_ARRAY_CASE
7459 7465
7460 case FAST_DOUBLE_ELEMENTS: 7466 case FAST_DOUBLE_ELEMENTS:
7461 case FAST_HOLEY_DOUBLE_ELEMENTS: 7467 case FAST_HOLEY_DOUBLE_ELEMENTS:
7462 break; 7468 break;
7463 case FAST_SMI_ELEMENTS: 7469 case FAST_SMI_ELEMENTS:
7464 case FAST_HOLEY_SMI_ELEMENTS: 7470 case FAST_HOLEY_SMI_ELEMENTS:
7465 break; 7471 break;
7466 case FAST_ELEMENTS: 7472 case FAST_ELEMENTS:
7467 case FAST_HOLEY_ELEMENTS: 7473 case FAST_HOLEY_ELEMENTS:
7468 case DICTIONARY_ELEMENTS: { 7474 case DICTIONARY_ELEMENTS:
7475 case FAST_STRING_WRAPPER_ELEMENTS:
7476 case SLOW_STRING_WRAPPER_ELEMENTS: {
7469 FixedArray* elements = FixedArray::cast(this->elements()); 7477 FixedArray* elements = FixedArray::cast(this->elements());
7470 if (ReferencesObjectFromElements(elements, kind, obj)) return true; 7478 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
7471 break; 7479 break;
7472 } 7480 }
7473 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 7481 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
7474 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 7482 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
7475 FixedArray* parameter_map = FixedArray::cast(elements()); 7483 FixedArray* parameter_map = FixedArray::cast(elements());
7476 // Check the mapped parameters. 7484 // Check the mapped parameters.
7477 int length = parameter_map->length(); 7485 int length = parameter_map->length();
7478 for (int i = 2; i < length; ++i) { 7486 for (int i = 2; i < length; ++i) {
7479 Object* value = parameter_map->get(i); 7487 Object* value = parameter_map->get(i);
7480 if (!value->IsTheHole() && value == obj) return true; 7488 if (!value->IsTheHole() && value == obj) return true;
7481 } 7489 }
7482 // Check the arguments. 7490 // Check the arguments.
7483 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 7491 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7484 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : 7492 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
7485 FAST_HOLEY_ELEMENTS; 7493 FAST_HOLEY_ELEMENTS;
7486 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; 7494 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
7487 break; 7495 break;
7488 } 7496 }
7497 case NO_ELEMENTS:
7498 break;
7489 } 7499 }
7490 7500
7491 // For functions check the context. 7501 // For functions check the context.
7492 if (IsJSFunction()) { 7502 if (IsJSFunction()) {
7493 // Get the constructor function for arguments array. 7503 // Get the constructor function for arguments array.
7494 Map* arguments_map = 7504 Map* arguments_map =
7495 heap->isolate()->context()->native_context()->sloppy_arguments_map(); 7505 heap->isolate()->context()->native_context()->sloppy_arguments_map();
7496 JSFunction* arguments_function = 7506 JSFunction* arguments_function =
7497 JSFunction::cast(arguments_map->GetConstructor()); 7507 JSFunction::cast(arguments_map->GetConstructor());
7498 7508
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
8124 JSObject); 8134 JSObject);
8125 if (copying) { 8135 if (copying) {
8126 // Creating object copy for literals. No strict mode needed. 8136 // Creating object copy for literals. No strict mode needed.
8127 JSObject::SetProperty(copy, name, result, SLOPPY).Assert(); 8137 JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
8128 } 8138 }
8129 } 8139 }
8130 } 8140 }
8131 } 8141 }
8132 8142
8133 // Deep copy own elements. 8143 // Deep copy own elements.
8134 // Pixel elements cannot be created using an object literal.
8135 DCHECK(!copy->HasFixedTypedArrayElements());
8136 switch (kind) { 8144 switch (kind) {
8137 case FAST_SMI_ELEMENTS:
8138 case FAST_ELEMENTS: 8145 case FAST_ELEMENTS:
8139 case FAST_HOLEY_SMI_ELEMENTS:
8140 case FAST_HOLEY_ELEMENTS: { 8146 case FAST_HOLEY_ELEMENTS: {
8141 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); 8147 Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
8142 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { 8148 if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
8143 #ifdef DEBUG 8149 #ifdef DEBUG
8144 for (int i = 0; i < elements->length(); i++) { 8150 for (int i = 0; i < elements->length(); i++) {
8145 DCHECK(!elements->get(i)->IsJSObject()); 8151 DCHECK(!elements->get(i)->IsJSObject());
8146 } 8152 }
8147 #endif 8153 #endif
8148 } else { 8154 } else {
8149 for (int i = 0; i < elements->length(); i++) { 8155 for (int i = 0; i < elements->length(); i++) {
8150 Handle<Object> value(elements->get(i), isolate); 8156 Handle<Object> value(elements->get(i), isolate);
8151 DCHECK(value->IsSmi() ||
8152 value->IsTheHole() ||
8153 (IsFastObjectElementsKind(copy->GetElementsKind())));
8154 if (value->IsJSObject()) { 8157 if (value->IsJSObject()) {
8155 Handle<JSObject> result; 8158 Handle<JSObject> result;
8156 ASSIGN_RETURN_ON_EXCEPTION( 8159 ASSIGN_RETURN_ON_EXCEPTION(
8157 isolate, result, 8160 isolate, result,
8158 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), 8161 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8159 JSObject); 8162 JSObject);
8160 if (copying) { 8163 if (copying) {
8161 elements->set(i, *result); 8164 elements->set(i, *result);
8162 } 8165 }
8163 } 8166 }
(...skipping 20 matching lines...) Expand all
8184 } 8187 }
8185 } 8188 }
8186 } 8189 }
8187 } 8190 }
8188 break; 8191 break;
8189 } 8192 }
8190 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 8193 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8191 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 8194 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8192 UNIMPLEMENTED(); 8195 UNIMPLEMENTED();
8193 break; 8196 break;
8194 8197 case FAST_STRING_WRAPPER_ELEMENTS:
8198 case SLOW_STRING_WRAPPER_ELEMENTS:
8199 UNREACHABLE();
8200 break;
8195 8201
8196 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 8202 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
8197 case TYPE##_ELEMENTS: \ 8203 case TYPE##_ELEMENTS: \
8198 8204
8199 TYPED_ARRAYS(TYPED_ARRAY_CASE) 8205 TYPED_ARRAYS(TYPED_ARRAY_CASE)
8200 #undef TYPED_ARRAY_CASE 8206 #undef TYPED_ARRAY_CASE
8207 // Typed elements cannot be created using an object literal.
8208 UNREACHABLE();
8209 break;
8201 8210
8211 case FAST_SMI_ELEMENTS:
8212 case FAST_HOLEY_SMI_ELEMENTS:
8202 case FAST_DOUBLE_ELEMENTS: 8213 case FAST_DOUBLE_ELEMENTS:
8203 case FAST_HOLEY_DOUBLE_ELEMENTS: 8214 case FAST_HOLEY_DOUBLE_ELEMENTS:
8215 case NO_ELEMENTS:
8204 // No contained objects, nothing to do. 8216 // No contained objects, nothing to do.
8205 break; 8217 break;
8206 } 8218 }
8207 } 8219 }
8208 8220
8209 return copy; 8221 return copy;
8210 } 8222 }
8211 8223
8212 8224
8213 MaybeHandle<JSObject> JSObject::DeepWalk( 8225 MaybeHandle<JSObject> JSObject::DeepWalk(
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
8299 } 8311 }
8300 } 8312 }
8301 THROW_NEW_ERROR(isolate, 8313 THROW_NEW_ERROR(isolate,
8302 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), 8314 NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8303 Object); 8315 Object);
8304 } 8316 }
8305 8317
8306 8318
8307 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. 8319 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
8308 bool HasEnumerableElements(JSObject* object) { 8320 bool HasEnumerableElements(JSObject* object) {
8309 if (object->IsJSValue()) {
8310 Object* value = JSValue::cast(object)->value();
8311 if (value->IsString()) {
8312 if (String::cast(value)->length() > 0) return true;
8313 }
8314 }
8315 switch (object->GetElementsKind()) { 8321 switch (object->GetElementsKind()) {
8316 case FAST_SMI_ELEMENTS: 8322 case FAST_SMI_ELEMENTS:
8317 case FAST_ELEMENTS: 8323 case FAST_ELEMENTS:
8318 case FAST_DOUBLE_ELEMENTS: { 8324 case FAST_DOUBLE_ELEMENTS: {
8319 int length = object->IsJSArray() 8325 int length = object->IsJSArray()
8320 ? Smi::cast(JSArray::cast(object)->length())->value() 8326 ? Smi::cast(JSArray::cast(object)->length())->value()
8321 : object->elements()->length(); 8327 : object->elements()->length();
8322 return length > 0; 8328 return length > 0;
8323 } 8329 }
8324 case FAST_HOLEY_SMI_ELEMENTS: 8330 case FAST_HOLEY_SMI_ELEMENTS:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8356 } 8362 }
8357 case DICTIONARY_ELEMENTS: { 8363 case DICTIONARY_ELEMENTS: {
8358 SeededNumberDictionary* elements = 8364 SeededNumberDictionary* elements =
8359 SeededNumberDictionary::cast(object->elements()); 8365 SeededNumberDictionary::cast(object->elements());
8360 return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0; 8366 return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0;
8361 } 8367 }
8362 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 8368 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8363 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 8369 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8364 // We're approximating non-empty arguments objects here. 8370 // We're approximating non-empty arguments objects here.
8365 return true; 8371 return true;
8372 case FAST_STRING_WRAPPER_ELEMENTS:
8373 case SLOW_STRING_WRAPPER_ELEMENTS:
8374 if (String::cast(JSValue::cast(object)->value())->length() > 0) {
8375 return true;
8376 }
8377 return object->elements()->length() > 0;
8378 case NO_ELEMENTS:
8379 return false;
8366 } 8380 }
8367 UNREACHABLE(); 8381 UNREACHABLE();
8368 return true; 8382 return true;
8369 } 8383 }
8370 8384
8371 8385
8372 // Tests for the fast common case for property enumeration: 8386 // Tests for the fast common case for property enumeration:
8373 // - This object and all prototypes has an enum cache (which means that 8387 // - This object and all prototypes has an enum cache (which means that
8374 // it is no proxy, has no interceptors and needs no access checks). 8388 // it is no proxy, has no interceptors and needs no access checks).
8375 // - This object has no elements. 8389 // - This object has no elements.
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
8588 if (result.IsEmpty()) return Just(true); 8602 if (result.IsEmpty()) return Just(true);
8589 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || 8603 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
8590 (v8::Utils::OpenHandle(*result)->IsJSObject() && 8604 (v8::Utils::OpenHandle(*result)->IsJSObject() &&
8591 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) 8605 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))
8592 ->HasSloppyArgumentsElements())); 8606 ->HasSloppyArgumentsElements()));
8593 // The accumulator takes care of string/symbol filtering. 8607 // The accumulator takes care of string/symbol filtering.
8594 if (type == kIndexed) { 8608 if (type == kIndexed) {
8595 accumulator->AddElementKeysFromInterceptor( 8609 accumulator->AddElementKeysFromInterceptor(
8596 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); 8610 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)));
8597 } else { 8611 } else {
8598 accumulator->AddKeys( 8612 accumulator->AddKeys(Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)),
8599 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); 8613 DO_NOT_CONVERT);
8600 } 8614 }
8601 return Just(true); 8615 return Just(true);
8602 } 8616 }
8603 8617
8604 8618
8605 // Returns |true| on success, |false| if prototype walking should be stopped, 8619 // Returns |true| on success, |false| if prototype walking should be stopped,
8606 // |nothing| if an exception was thrown. 8620 // |nothing| if an exception was thrown.
8607 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, 8621 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate,
8608 Handle<JSReceiver> receiver, 8622 Handle<JSReceiver> receiver,
8609 Handle<JSObject> object, 8623 Handle<JSObject> object,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
8645 // use the cache says yes, so we should not create a cache. 8659 // use the cache says yes, so we should not create a cache.
8646 Handle<JSFunction> arguments_function( 8660 Handle<JSFunction> arguments_function(
8647 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 8661 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
8648 bool cache_enum_length = 8662 bool cache_enum_length =
8649 ((object->map()->GetConstructor() != *arguments_function) && 8663 ((object->map()->GetConstructor() != *arguments_function) &&
8650 !object->IsJSValue() && !object->IsAccessCheckNeeded() && 8664 !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
8651 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); 8665 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
8652 // Compute the property keys and cache them if possible. 8666 // Compute the property keys and cache them if possible.
8653 Handle<FixedArray> enum_keys = 8667 Handle<FixedArray> enum_keys =
8654 JSObject::GetEnumPropertyKeys(object, cache_enum_length); 8668 JSObject::GetEnumPropertyKeys(object, cache_enum_length);
8655 accumulator->AddKeys(enum_keys); 8669 accumulator->AddKeys(enum_keys, DO_NOT_CONVERT);
8656 } else { 8670 } else {
8657 object->CollectOwnPropertyNames(accumulator, *filter); 8671 object->CollectOwnPropertyNames(accumulator, *filter);
8658 } 8672 }
8659 8673
8660 // Add the property keys from the interceptor. 8674 // Add the property keys from the interceptor.
8661 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, 8675 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
8662 kNamed>(isolate, receiver, object, *filter, 8676 kNamed>(isolate, receiver, object, *filter,
8663 accumulator); 8677 accumulator);
8664 MAYBE_RETURN(success, Nothing<bool>()); 8678 MAYBE_RETURN(success, Nothing<bool>());
8665 return Just(true); 8679 return Just(true);
(...skipping 7099 matching lines...) Expand 10 before | Expand all | Expand 10 after
15765 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); 15779 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
15766 } 15780 }
15767 return false; 15781 return false;
15768 } 15782 }
15769 15783
15770 15784
15771 static ElementsKind BestFittingFastElementsKind(JSObject* object) { 15785 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
15772 if (object->HasSloppyArgumentsElements()) { 15786 if (object->HasSloppyArgumentsElements()) {
15773 return FAST_SLOPPY_ARGUMENTS_ELEMENTS; 15787 return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
15774 } 15788 }
15789 if (object->HasStringWrapperElements()) {
15790 return FAST_STRING_WRAPPER_ELEMENTS;
15791 }
15775 DCHECK(object->HasDictionaryElements()); 15792 DCHECK(object->HasDictionaryElements());
15776 SeededNumberDictionary* dictionary = object->element_dictionary(); 15793 SeededNumberDictionary* dictionary = object->element_dictionary();
15777 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; 15794 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
15778 for (int i = 0; i < dictionary->Capacity(); i++) { 15795 for (int i = 0; i < dictionary->Capacity(); i++) {
15779 Object* key = dictionary->KeyAt(i); 15796 Object* key = dictionary->KeyAt(i);
15780 if (key->IsNumber()) { 15797 if (key->IsNumber()) {
15781 Object* value = dictionary->ValueAt(i); 15798 Object* value = dictionary->ValueAt(i);
15782 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; 15799 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
15783 if (!value->IsSmi()) { 15800 if (!value->IsSmi()) {
15784 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS; 15801 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
15848 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); 15865 old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
15849 } 15866 }
15850 } 15867 }
15851 15868
15852 ElementsKind kind = object->GetElementsKind(); 15869 ElementsKind kind = object->GetElementsKind();
15853 FixedArrayBase* elements = object->elements(); 15870 FixedArrayBase* elements = object->elements();
15854 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; 15871 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15855 if (IsSloppyArgumentsElements(kind)) { 15872 if (IsSloppyArgumentsElements(kind)) {
15856 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); 15873 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
15857 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 15874 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15875 } else if (IsStringWrapperElementsKind(kind)) {
15876 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
15858 } 15877 }
15859 15878
15860 if (attributes != NONE) { 15879 if (attributes != NONE) {
15861 kind = dictionary_kind; 15880 kind = dictionary_kind;
15862 } else if (elements->IsSeededNumberDictionary()) { 15881 } else if (elements->IsSeededNumberDictionary()) {
15863 kind = ShouldConvertToFastElements(*object, 15882 kind = ShouldConvertToFastElements(*object,
15864 SeededNumberDictionary::cast(elements), 15883 SeededNumberDictionary::cast(elements),
15865 index, &new_capacity) 15884 index, &new_capacity)
15866 ? BestFittingFastElementsKind(*object) 15885 ? BestFittingFastElementsKind(*object)
15867 : dictionary_kind; // Overwrite in case of arguments. 15886 : dictionary_kind; // Overwrite in case of arguments.
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
16142 case FAST_SMI_ELEMENTS: 16161 case FAST_SMI_ELEMENTS:
16143 case FAST_DOUBLE_ELEMENTS: 16162 case FAST_DOUBLE_ELEMENTS:
16144 case FAST_ELEMENTS: 16163 case FAST_ELEMENTS:
16145 return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value() 16164 return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
16146 : store->length(); 16165 : store->length();
16147 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 16166 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16148 store = FixedArray::cast(FixedArray::cast(store)->get(1)); 16167 store = FixedArray::cast(FixedArray::cast(store)->get(1));
16149 // Fall through. 16168 // Fall through.
16150 case FAST_HOLEY_SMI_ELEMENTS: 16169 case FAST_HOLEY_SMI_ELEMENTS:
16151 case FAST_HOLEY_ELEMENTS: 16170 case FAST_HOLEY_ELEMENTS:
16171 case FAST_STRING_WRAPPER_ELEMENTS:
16152 return FastHoleyElementsUsage(this, FixedArray::cast(store)); 16172 return FastHoleyElementsUsage(this, FixedArray::cast(store));
16153 case FAST_HOLEY_DOUBLE_ELEMENTS: 16173 case FAST_HOLEY_DOUBLE_ELEMENTS:
16154 if (elements()->length() == 0) return 0; 16174 if (elements()->length() == 0) return 0;
16155 return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store)); 16175 return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
16156 16176
16157 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 16177 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
16178 case SLOW_STRING_WRAPPER_ELEMENTS:
16158 case DICTIONARY_ELEMENTS: 16179 case DICTIONARY_ELEMENTS:
16180 case NO_ELEMENTS:
16159 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 16181 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
16160 case TYPE##_ELEMENTS: \ 16182 case TYPE##_ELEMENTS: \
16161 16183
16162 TYPED_ARRAYS(TYPED_ARRAY_CASE) 16184 TYPED_ARRAYS(TYPED_ARRAY_CASE)
16163 #undef TYPED_ARRAY_CASE 16185 #undef TYPED_ARRAY_CASE
16164 UNREACHABLE(); 16186 UNREACHABLE();
16165 } 16187 }
16166 return 0; 16188 return 0;
16167 } 16189 }
16168 16190
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
16420 PropertyDetails details = descs->GetDetails(i); 16442 PropertyDetails details = descs->GetDetails(i);
16421 if ((details.attributes() & filter) != 0) continue; 16443 if ((details.attributes() & filter) != 0) continue;
16422 if (filter & ONLY_ALL_CAN_READ) { 16444 if (filter & ONLY_ALL_CAN_READ) {
16423 if (details.kind() != kAccessor) continue; 16445 if (details.kind() != kAccessor) continue;
16424 Object* accessors = descs->GetValue(i); 16446 Object* accessors = descs->GetValue(i);
16425 if (!accessors->IsAccessorInfo()) continue; 16447 if (!accessors->IsAccessorInfo()) continue;
16426 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; 16448 if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
16427 } 16449 }
16428 Name* key = descs->GetKey(i); 16450 Name* key = descs->GetKey(i);
16429 if (key->FilterKey(filter)) continue; 16451 if (key->FilterKey(filter)) continue;
16430 keys->AddKey(key); 16452 keys->AddKey(key, DO_NOT_CONVERT);
16431 } 16453 }
16432 } else if (IsJSGlobalObject()) { 16454 } else if (IsJSGlobalObject()) {
16433 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); 16455 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
16434 } else { 16456 } else {
16435 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); 16457 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter);
16436 } 16458 }
16437 } 16459 }
16438 16460
16439 16461
16440 int JSObject::NumberOfOwnElements(PropertyFilter filter) { 16462 int JSObject::NumberOfOwnElements(PropertyFilter filter) {
16441 // Fast case for objects with no elements. 16463 // Fast case for objects with no elements.
16442 if (!IsJSValue() && HasFastElements()) { 16464 if (!IsJSValue() && HasFastElements()) {
16443 uint32_t length = 16465 uint32_t length =
16444 IsJSArray() 16466 IsJSArray()
16445 ? static_cast<uint32_t>( 16467 ? static_cast<uint32_t>(
16446 Smi::cast(JSArray::cast(this)->length())->value()) 16468 Smi::cast(JSArray::cast(this)->length())->value())
16447 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); 16469 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length());
16448 if (length == 0) return 0; 16470 if (length == 0) return 0;
16449 } 16471 }
16450 // Compute the number of enumerable elements. 16472 // Compute the number of enumerable elements.
16451 return GetOwnElementKeys(NULL, filter); 16473 return GetOwnElementKeys(NULL, filter);
16452 } 16474 }
16453 16475
16454 16476
16455 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, 16477 void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
16456 KeyAccumulator* keys, 16478 KeyAccumulator* keys,
16457 PropertyFilter filter) { 16479 PropertyFilter filter) {
16458 if (filter & SKIP_STRINGS) return; 16480 if (filter & SKIP_STRINGS) return;
16459 uint32_t string_keys = 0;
16460
16461 // If this is a String wrapper, add the string indices first,
16462 // as they're guaranteed to precede the elements in numerical order
16463 // and ascending order is required by ECMA-262, 6th, 9.1.12.
16464 if (object->IsJSValue()) {
16465 Object* val = JSValue::cast(*object)->value();
16466 if (val->IsString() && (filter & ONLY_ALL_CAN_READ) == 0) {
16467 String* str = String::cast(val);
16468 string_keys = str->length();
16469 for (uint32_t i = 0; i < string_keys; i++) {
16470 keys->AddKey(i);
16471 }
16472 }
16473 }
16474 ElementsAccessor* accessor = object->GetElementsAccessor(); 16481 ElementsAccessor* accessor = object->GetElementsAccessor();
16475 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); 16482 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
16476 } 16483 }
16477 16484
16478 16485
16479 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { 16486 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
16480 int counter = 0; 16487 int counter = 0;
16481 16488
16482 // If this is a String wrapper, add the string indices first, 16489 // If this is a String wrapper, add the string indices first,
16483 // as they're guaranteed to precede the elements in numerical order 16490 // as they're guaranteed to precede the elements in numerical order
16484 // and ascending order is required by ECMA-262, 6th, 9.1.12. 16491 // and ascending order is required by ECMA-262, 6th, 9.1.12.
16485 if (IsJSValue()) { 16492 if (IsJSValue()) {
Jakob Kummerow 2016/01/26 14:21:24 Intentionally not ElementsAccessor-izing this beca
16486 Object* val = JSValue::cast(this)->value(); 16493 Object* val = JSValue::cast(this)->value();
16487 if (val->IsString()) { 16494 if (val->IsString()) {
16488 String* str = String::cast(val); 16495 String* str = String::cast(val);
16489 if (storage) { 16496 if (storage) {
16490 for (int i = 0; i < str->length(); i++) { 16497 for (int i = 0; i < str->length(); i++) {
16491 storage->set(counter + i, Smi::FromInt(i)); 16498 storage->set(counter + i, Smi::FromInt(i));
16492 } 16499 }
16493 } 16500 }
16494 counter += str->length(); 16501 counter += str->length();
16495 } 16502 }
16496 } 16503 }
16497 16504
16498 switch (GetElementsKind()) { 16505 switch (GetElementsKind()) {
16499 case FAST_SMI_ELEMENTS: 16506 case FAST_SMI_ELEMENTS:
16500 case FAST_ELEMENTS: 16507 case FAST_ELEMENTS:
16501 case FAST_HOLEY_SMI_ELEMENTS: 16508 case FAST_HOLEY_SMI_ELEMENTS:
16502 case FAST_HOLEY_ELEMENTS: { 16509 case FAST_HOLEY_ELEMENTS:
16510 case FAST_STRING_WRAPPER_ELEMENTS: {
16503 int length = IsJSArray() ? 16511 int length = IsJSArray() ?
16504 Smi::cast(JSArray::cast(this)->length())->value() : 16512 Smi::cast(JSArray::cast(this)->length())->value() :
16505 FixedArray::cast(elements())->length(); 16513 FixedArray::cast(elements())->length();
16506 for (int i = 0; i < length; i++) { 16514 for (int i = 0; i < length; i++) {
16507 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 16515 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
16508 if (storage != NULL) { 16516 if (storage != NULL) {
16509 storage->set(counter, Smi::FromInt(i)); 16517 storage->set(counter, Smi::FromInt(i));
16510 } 16518 }
16511 counter++; 16519 counter++;
16512 } 16520 }
(...skipping 28 matching lines...) Expand all
16541 while (counter < length) { 16549 while (counter < length) {
16542 if (storage != NULL) { 16550 if (storage != NULL) {
16543 storage->set(counter, Smi::FromInt(counter)); 16551 storage->set(counter, Smi::FromInt(counter));
16544 } 16552 }
16545 counter++; 16553 counter++;
16546 } 16554 }
16547 DCHECK(!storage || storage->length() >= counter); 16555 DCHECK(!storage || storage->length() >= counter);
16548 break; 16556 break;
16549 } 16557 }
16550 16558
16551 case DICTIONARY_ELEMENTS: { 16559 case DICTIONARY_ELEMENTS:
16560 case SLOW_STRING_WRAPPER_ELEMENTS: {
16552 if (storage != NULL) { 16561 if (storage != NULL) {
16553 element_dictionary()->CopyKeysTo(storage, counter, filter, 16562 element_dictionary()->CopyKeysTo(storage, counter, filter,
16554 SeededNumberDictionary::SORTED); 16563 SeededNumberDictionary::SORTED);
16555 } 16564 }
16556 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); 16565 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
16557 break; 16566 break;
16558 } 16567 }
16559 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 16568 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16560 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 16569 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
16561 FixedArray* parameter_map = FixedArray::cast(elements()); 16570 FixedArray* parameter_map = FixedArray::cast(elements());
(...skipping 29 matching lines...) Expand all
16591 ++counter; 16600 ++counter;
16592 } 16601 }
16593 } 16602 }
16594 for (; i < backing_length; ++i) { 16603 for (; i < backing_length; ++i) {
16595 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); 16604 if (storage != NULL) storage->set(counter, Smi::FromInt(i));
16596 ++counter; 16605 ++counter;
16597 } 16606 }
16598 } 16607 }
16599 break; 16608 break;
16600 } 16609 }
16610 case NO_ELEMENTS:
16611 break;
16601 } 16612 }
16602 16613
16603 DCHECK(!storage || storage->length() == counter); 16614 DCHECK(!storage || storage->length() == counter);
16604 return counter; 16615 return counter;
16605 } 16616 }
16606 16617
16607 16618
16608 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, 16619 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
16609 Handle<Object> object) { 16620 Handle<Object> object) {
16610 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); 16621 if (object->IsUndefined()) return isolate->factory()->undefined_to_string();
(...skipping 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after
18488 array->set(array_size++, Smi::FromInt(i)); 18499 array->set(array_size++, Smi::FromInt(i));
18489 } 18500 }
18490 18501
18491 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); 18502 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
18492 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); 18503 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
18493 std::sort(start, start + array_size, cmp); 18504 std::sort(start, start + array_size, cmp);
18494 } 18505 }
18495 18506
18496 for (int i = 0; i < array_size; i++) { 18507 for (int i = 0; i < array_size; i++) {
18497 int index = Smi::cast(array->get(i))->value(); 18508 int index = Smi::cast(array->get(i))->value();
18498 keys->AddKey(dictionary->KeyAt(index)); 18509 keys->AddKey(dictionary->KeyAt(index), DO_NOT_CONVERT);
18499 } 18510 }
18500 } 18511 }
18501 18512
18502 18513
18503 // Backwards lookup (slow). 18514 // Backwards lookup (slow).
18504 template<typename Derived, typename Shape, typename Key> 18515 template<typename Derived, typename Shape, typename Key>
18505 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { 18516 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
18506 int capacity = this->Capacity(); 18517 int capacity = this->Capacity();
18507 for (int i = 0; i < capacity; i++) { 18518 for (int i = 0; i < capacity; i++) {
18508 Object* k = this->KeyAt(i); 18519 Object* k = this->KeyAt(i);
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after
19745 if (cell->value() != *new_value) { 19756 if (cell->value() != *new_value) {
19746 cell->set_value(*new_value); 19757 cell->set_value(*new_value);
19747 Isolate* isolate = cell->GetIsolate(); 19758 Isolate* isolate = cell->GetIsolate();
19748 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19759 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19749 isolate, DependentCode::kPropertyCellChangedGroup); 19760 isolate, DependentCode::kPropertyCellChangedGroup);
19750 } 19761 }
19751 } 19762 }
19752 19763
19753 } // namespace internal 19764 } // namespace internal
19754 } // namespace v8 19765 } // namespace v8
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698