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

Side by Side Diff: src/objects.cc

Issue 1194023004: Let AddDictionaryElement / AddFastElement purely add, move transition heuristics to AddDataElement (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add test Created 5 years, 6 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
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/arguments.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <iomanip> 5 #include <iomanip>
6 #include <sstream> 6 #include <sstream>
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 12267 matching lines...) Expand 10 before | Expand all | Expand 10 after
12278 void JSObject::ValidateElements(Handle<JSObject> object) { 12278 void JSObject::ValidateElements(Handle<JSObject> object) {
12279 #ifdef ENABLE_SLOW_DCHECKS 12279 #ifdef ENABLE_SLOW_DCHECKS
12280 if (FLAG_enable_slow_asserts) { 12280 if (FLAG_enable_slow_asserts) {
12281 ElementsAccessor* accessor = object->GetElementsAccessor(); 12281 ElementsAccessor* accessor = object->GetElementsAccessor();
12282 accessor->Validate(object); 12282 accessor->Validate(object);
12283 } 12283 }
12284 #endif 12284 #endif
12285 } 12285 }
12286 12286
12287 12287
12288 static void AddDictionaryElement(Handle<JSObject> object,
12289 Handle<SeededNumberDictionary> dictionary,
12290 uint32_t index, Handle<Object> value,
12291 PropertyAttributes attributes) {
12292 // TODO(verwaest): Handle with the elements accessor.
12293 // Insert element in the dictionary.
12294 #ifdef DEBUG
12295 int entry = dictionary->FindEntry(index);
12296 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry);
12297 #endif
12298
12299 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
12300 Handle<SeededNumberDictionary> new_dictionary =
12301 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details);
12302
12303 if (*dictionary == *new_dictionary) return;
12304
12305 if (object->HasSloppyArgumentsElements()) {
12306 FixedArray::cast(object->elements())->set(1, *new_dictionary);
12307 } else {
12308 object->set_elements(*new_dictionary);
12309 }
12310 }
12311
12312
12288 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object, 12313 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object,
12289 uint32_t index, 12314 uint32_t index,
12290 Handle<Object> value, 12315 Handle<Object> value,
12291 PropertyAttributes attributes) { 12316 PropertyAttributes attributes) {
12292 // TODO(verwaest): Handle with the elements accessor. 12317 // TODO(verwaest): Handle with the elements accessor.
12293 Isolate* isolate = object->GetIsolate(); 12318 Isolate* isolate = object->GetIsolate();
12294 12319
12295 DCHECK(object->HasDictionaryArgumentsElements()); 12320 DCHECK(object->HasDictionaryArgumentsElements());
12296 12321
12297 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); 12322 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12298 uint32_t length = parameter_map->length(); 12323 uint32_t length = parameter_map->length();
12299 Handle<Object> probe = 12324 Handle<Object> probe =
12300 index < length - 2 12325 index < length - 2
12301 ? handle(parameter_map->get(index + 2), isolate) 12326 ? handle(parameter_map->get(index + 2), isolate)
12302 : Handle<Object>::cast(isolate->factory()->the_hole_value()); 12327 : Handle<Object>::cast(isolate->factory()->the_hole_value());
12303 if (!probe->IsTheHole()) { 12328 if (!probe->IsTheHole()) {
12304 Handle<Context> context(Context::cast(parameter_map->get(0))); 12329 Handle<Context> context(Context::cast(parameter_map->get(0)));
12305 int context_index = Handle<Smi>::cast(probe)->value(); 12330 int context_index = Handle<Smi>::cast(probe)->value();
12306 DCHECK(!context->get(context_index)->IsTheHole()); 12331 DCHECK(!context->get(context_index)->IsTheHole());
12307 context->set(context_index, *value); 12332 context->set(context_index, *value);
12308 12333
12309 DCHECK_NE(NONE, attributes); 12334 DCHECK_NE(NONE, attributes);
12310 12335
12311 // Redefining attributes of an aliased element destroys fast aliasing. 12336 // Redefining attributes of an aliased element destroys fast aliasing.
12312 parameter_map->set_the_hole(index + 2); 12337 parameter_map->set_the_hole(index + 2);
12313 // For elements that are still writable we re-establish slow aliasing. 12338 // For elements that are still writable we re-establish slow aliasing.
12314 if ((attributes & READ_ONLY) == 0) { 12339 if ((attributes & READ_ONLY) == 0) {
12315 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); 12340 value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
12316 } 12341 }
12317 AddDictionaryElement(object, index, value, attributes); 12342 Handle<SeededNumberDictionary> dictionary(
12343 SeededNumberDictionary::cast(parameter_map->get(1)));
12344 AddDictionaryElement(object, dictionary, index, value, attributes);
12318 } else { 12345 } else {
12319 SetDictionaryElement(object, index, value, attributes); 12346 SetDictionaryElement(object, index, value, attributes);
12320 } 12347 }
12321 } 12348 }
12322 12349
12323 12350
12324 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index, 12351 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
12325 Handle<Object> value, 12352 Handle<Object> value,
12326 PropertyAttributes attributes) { 12353 PropertyAttributes attributes) {
12327 // TODO(verwaest): Handle with the elements accessor. 12354 // TODO(verwaest): Handle with the elements accessor.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
12359 context->set(context_index, *value); 12386 context->set(context_index, *value);
12360 // For elements that are still writable we keep slow aliasing. 12387 // For elements that are still writable we keep slow aliasing.
12361 if (!details.IsReadOnly()) value = element; 12388 if (!details.IsReadOnly()) value = element;
12362 } 12389 }
12363 } 12390 }
12364 12391
12365 dictionary->ValueAtPut(entry, *value); 12392 dictionary->ValueAtPut(entry, *value);
12366 } 12393 }
12367 12394
12368 12395
12369 static bool ShouldConvertToFastElements(SeededNumberDictionary* dictionary,
12370 uint32_t array_size) {
12371 // If properties with non-standard attributes or accessors were added, we
12372 // cannot go back to fast elements.
12373 if (dictionary->requires_slow_elements()) return false;
12374 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
12375 SeededNumberDictionary::kEntrySize;
12376 return 2 * dictionary_size >= array_size;
12377 }
12378
12379
12380 void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index,
12381 Handle<Object> value,
12382 PropertyAttributes attributes) {
12383 // TODO(verwaest): Handle with the elements accessor.
12384 // Insert element in the dictionary.
12385 DCHECK(object->HasDictionaryElements() ||
12386 object->HasDictionaryArgumentsElements());
12387 DCHECK(object->map()->is_extensible());
12388
12389 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12390 bool is_arguments = object->HasSloppyArgumentsElements();
12391 Handle<SeededNumberDictionary> dictionary(
12392 is_arguments ? SeededNumberDictionary::cast(elements->get(1))
12393 : SeededNumberDictionary::cast(*elements));
12394
12395 #ifdef DEBUG
12396 int entry = dictionary->FindEntry(index);
12397 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry);
12398 #endif
12399
12400 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
12401 Handle<SeededNumberDictionary> new_dictionary =
12402 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details);
12403
12404 if (*dictionary != *new_dictionary) {
12405 if (is_arguments) {
12406 elements->set(1, *new_dictionary);
12407 } else {
12408 object->set_elements(*new_dictionary);
12409 }
12410 }
12411
12412 uint32_t length = 0;
12413 if (object->IsJSArray()) {
12414 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&length));
12415 if (index >= length) {
12416 length = index + 1;
12417 Isolate* isolate = object->GetIsolate();
12418 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
12419 JSArray::cast(*object)->set_length(*length_obj);
12420 }
12421 } else if (!new_dictionary->requires_slow_elements()) {
12422 length = new_dictionary->max_number_key() + 1;
12423 }
12424
12425 // Attempt to put this object back in fast case.
12426 if (object->HasDenseElements() &&
12427 ShouldConvertToFastElements(*new_dictionary, length)) {
12428 ElementsKind to_kind = object->BestFittingFastElementsKind();
12429 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12430 accessor->GrowCapacityAndConvert(object, length);
12431 #ifdef DEBUG
12432 if (FLAG_trace_normalization) {
12433 OFStream os(stdout);
12434 os << "Object elements are fast case again:\n";
12435 object->Print(os);
12436 }
12437 #endif
12438 }
12439 }
12440
12441
12442 // static 12396 // static
12443 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12397 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12444 uint32_t index, Handle<Object> value, 12398 uint32_t index, Handle<Object> value,
12445 LanguageMode language_mode) { 12399 LanguageMode language_mode) {
12446 Isolate* isolate = object->GetIsolate(); 12400 Isolate* isolate = object->GetIsolate();
12447 LookupIterator it(isolate, object, index); 12401 LookupIterator it(isolate, object, index);
12448 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); 12402 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
12449 } 12403 }
12450 12404
12451 12405
12452 static void AddFastElement(Handle<JSObject> object, uint32_t index, 12406 static void AddFastElement(Handle<JSObject> object, uint32_t index,
12453 Handle<Object> value, ElementsKind from_kind, 12407 Handle<Object> value, ElementsKind from_kind,
12454 uint32_t capacity, uint32_t new_capacity) { 12408 uint32_t array_length, uint32_t capacity,
12455 // Check if the length property of this object needs to be updated. 12409 uint32_t new_capacity) {
12456 uint32_t array_length = 0; 12410 bool introduces_holes = !object->IsJSArray() || index > array_length;
12457 bool introduces_holes = true;
12458 if (object->IsJSArray()) {
12459 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
12460 introduces_holes = index > array_length;
12461 } else {
12462 introduces_holes = index >= capacity;
12463 }
12464 12411
12465 ElementsKind to_kind = value->OptimalElementsKind(); 12412 ElementsKind to_kind = value->OptimalElementsKind();
12466 if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind); 12413 if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind);
12467 to_kind = IsMoreGeneralElementsKindTransition(from_kind, to_kind) ? to_kind 12414 to_kind = IsMoreGeneralElementsKindTransition(from_kind, to_kind) ? to_kind
12468 : from_kind; 12415 : from_kind;
12469 if (introduces_holes) to_kind = GetHoleyElementsKind(to_kind); 12416 if (introduces_holes) to_kind = GetHoleyElementsKind(to_kind);
12470 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind); 12417 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12471 12418
12472 // Increase backing store capacity if that's been decided previously. 12419 // Increase backing store capacity if that's been decided previously.
12473 if (capacity != new_capacity || IsDictionaryElementsKind(from_kind) || 12420 // The capacity is indicated as 0 if the incoming object was dictionary or
12421 // slow-mode sloppy arguments.
12422 if (capacity != new_capacity ||
12474 IsFastDoubleElementsKind(from_kind) != 12423 IsFastDoubleElementsKind(from_kind) !=
12475 IsFastDoubleElementsKind(to_kind)) { 12424 IsFastDoubleElementsKind(to_kind)) {
12476 accessor->GrowCapacityAndConvert(object, new_capacity); 12425 accessor->GrowCapacityAndConvert(object, new_capacity);
12477 } else if (from_kind != to_kind) { 12426 } else if (from_kind != to_kind) {
12478 JSObject::TransitionElementsKind(object, to_kind); 12427 JSObject::TransitionElementsKind(object, to_kind);
12479 } 12428 }
12480 12429
12481 if (object->IsJSArray() && index >= array_length) {
12482 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12483 }
12484
12485 accessor->Set(object->elements(), index, *value); 12430 accessor->Set(object->elements(), index, *value);
12486 } 12431 }
12487 12432
12488 12433
12434 // Do we want to keep fast elements when adding an element at |index|? Returns
12435 // |new_capacity| indicating to which capacity the object should be increased.
12436 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
12437 uint32_t index,
12438 uint32_t* new_capacity) {
12439 STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
12440 JSObject::kMaxUncheckedFastElementsLength);
12441 if (index < capacity) {
12442 *new_capacity = capacity;
12443 return false;
12444 }
12445 if (index - capacity >= JSObject::kMaxGap) return true;
12446 *new_capacity = JSObject::NewElementsCapacity(index + 1);
12447 DCHECK_LT(index, *new_capacity);
12448 if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
12449 (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
12450 object->GetHeap()->InNewSpace(object))) {
12451 return false;
12452 }
12453 // If the fast-case backing storage takes up roughly three times as
12454 // much space (in machine words) as a dictionary backing storage
12455 // would, the object should have slow elements.
12456 int old_capacity = 0;
12457 int used_elements = 0;
12458 object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
12459 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12460 SeededNumberDictionary::kEntrySize;
12461 return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
12462 }
12463
12464
12465 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
12466 if (HasFastElements()) {
12467 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12468 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12469 uint32_t new_capacity;
12470 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
12471 }
12472 return false;
12473 }
12474
12475
12476 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
12477 if (object->HasSloppyArgumentsElements()) return SLOPPY_ARGUMENTS_ELEMENTS;
12478 DCHECK(object->HasDictionaryElements());
12479 SeededNumberDictionary* dictionary = object->element_dictionary();
12480 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
12481 for (int i = 0; i < dictionary->Capacity(); i++) {
12482 Object* key = dictionary->KeyAt(i);
12483 if (key->IsNumber()) {
12484 Object* value = dictionary->ValueAt(i);
12485 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
12486 if (!value->IsSmi()) {
12487 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
12488 kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12489 }
12490 }
12491 }
12492 return kind;
12493 }
12494
12495
12496 static bool ShouldConvertToFastElements(JSObject* object,
12497 SeededNumberDictionary* dictionary,
12498 uint32_t index,
12499 uint32_t* new_capacity) {
12500 // If properties with non-standard attributes or accessors were added, we
12501 // cannot go back to fast elements.
12502 if (dictionary->requires_slow_elements()) return false;
12503
12504 // Adding a property with this index will require slow elements.
12505 if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
12506
12507 if (object->IsJSArray()) {
12508 Object* length = JSArray::cast(object)->length();
12509 if (!length->IsSmi()) return false;
12510 *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
12511 } else {
12512 *new_capacity = dictionary->max_number_key() + 1;
12513 }
12514 *new_capacity = Max(index + 1, *new_capacity);
12515
12516 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
12517 SeededNumberDictionary::kEntrySize;
12518 return 2 * dictionary_size >= *new_capacity;
12519 }
12520
12521
12489 // static 12522 // static
12490 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, 12523 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
12491 uint32_t index, 12524 uint32_t index,
12492 Handle<Object> value, 12525 Handle<Object> value,
12493 PropertyAttributes attributes) { 12526 PropertyAttributes attributes) {
12494 DCHECK(object->map()->is_extensible()); 12527 DCHECK(object->map()->is_extensible());
12495 12528
12496 Isolate* isolate = object->GetIsolate(); 12529 Isolate* isolate = object->GetIsolate();
12497 12530
12498 // TODO(verwaest): Use ElementAccessor. 12531 ElementsKind kind = object->GetElementsKind();
12532 bool handle_slow;
12533 uint32_t old_length = 0;
12534 uint32_t old_capacity = 0;
12535 uint32_t new_capacity = 0;
12536
12499 Handle<Object> old_length_handle; 12537 Handle<Object> old_length_handle;
12500 if (object->IsJSArray() && object->map()->is_observed()) { 12538 if (object->IsJSArray()) {
12501 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); 12539 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
12540 if (object->map()->is_observed()) {
12541 old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
12542 }
12502 } 12543 }
12503 12544
12504 ElementsKind kind = object->GetElementsKind(); 12545 Handle<SeededNumberDictionary> dictionary;
12505 bool handle_slow = IsDictionaryElementsKind(kind); 12546 FixedArrayBase* elements = object->elements();
12506 uint32_t capacity = 0; 12547 if (IsSloppyArgumentsElements(kind)) {
12507 uint32_t new_capacity = 0; 12548 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
12508 if (attributes != NONE) { 12549 }
12509 // TODO(verwaest): Move set_requires_slow_elements into NormalizeElements. 12550
12510 NormalizeElements(object)->set_requires_slow_elements(); 12551 if (elements->IsSeededNumberDictionary()) {
12511 handle_slow = true; 12552 dictionary = handle(SeededNumberDictionary::cast(elements));
12512 } else if (IsSloppyArgumentsElements(kind)) { 12553 handle_slow = attributes != NONE ||
12513 FixedArray* parameter_map = FixedArray::cast(object->elements()); 12554 !ShouldConvertToFastElements(*object, *dictionary, index,
12514 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 12555 &new_capacity);
12515 if (arguments->IsDictionary()) { 12556 if (!handle_slow) kind = BestFittingFastElementsKind(*object);
12516 handle_slow = true; 12557 } else {
12517 } else { 12558 old_capacity = static_cast<uint32_t>(elements->length());
12518 capacity = static_cast<uint32_t>(arguments->length());
12519 handle_slow =
12520 object->ShouldConvertToSlowElements(capacity, index, &new_capacity);
12521 if (handle_slow) NormalizeElements(object);
12522 }
12523 } else if (!handle_slow) {
12524 capacity = static_cast<uint32_t>(object->elements()->length());
12525 handle_slow = 12559 handle_slow =
12526 object->ShouldConvertToSlowElements(capacity, index, &new_capacity); 12560 attributes != NONE || ShouldConvertToSlowElements(*object, old_capacity,
12561 index, &new_capacity);
12527 if (handle_slow) { 12562 if (handle_slow) {
12528 NormalizeElements(object); 12563 dictionary = NormalizeElements(object);
12529 } else if (IsFastSmiOrObjectElementsKind(kind)) { 12564 } else if (IsFastSmiOrObjectElementsKind(kind)) {
12530 EnsureWritableFastElements(object); 12565 EnsureWritableFastElements(object);
12531 } 12566 }
12532 } 12567 }
12533 12568
12534 if (handle_slow) { 12569 if (handle_slow) {
12570 if (attributes != NONE) dictionary->set_requires_slow_elements();
12535 DCHECK(object->HasDictionaryElements() || 12571 DCHECK(object->HasDictionaryElements() ||
12536 object->HasDictionaryArgumentsElements()); 12572 object->HasDictionaryArgumentsElements());
12537 AddDictionaryElement(object, index, value, attributes); 12573 AddDictionaryElement(object, dictionary, index, value, attributes);
12538 } else { 12574 } else {
12539 AddFastElement(object, index, value, kind, capacity, new_capacity); 12575 AddFastElement(object, index, value, kind, old_length, old_capacity,
12576 new_capacity);
12540 } 12577 }
12541 12578
12542 if (!old_length_handle.is_null() && 12579 uint32_t new_length = old_length;
12543 !old_length_handle->SameValue(Handle<JSArray>::cast(object)->length())) { 12580 Handle<Object> new_length_handle;
12581 if (object->IsJSArray() && index >= old_length) {
12582 new_length = index + 1;
12583 new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
12584 JSArray::cast(*object)->set_length(*new_length_handle);
12585 }
12586
12587 if (!old_length_handle.is_null() && new_length != old_length) {
12544 // |old_length_handle| is kept null above unless the object is observed. 12588 // |old_length_handle| is kept null above unless the object is observed.
12545 DCHECK(object->map()->is_observed()); 12589 DCHECK(object->map()->is_observed());
12546 Handle<JSArray> array = Handle<JSArray>::cast(object); 12590 Handle<JSArray> array = Handle<JSArray>::cast(object);
12547 Handle<String> name = isolate->factory()->Uint32ToString(index); 12591 Handle<String> name = isolate->factory()->Uint32ToString(index);
12548 Handle<Object> new_length_handle(array->length(), isolate);
12549 uint32_t old_length = 0;
12550 uint32_t new_length = 0;
12551 CHECK(old_length_handle->ToArrayLength(&old_length));
12552 CHECK(new_length_handle->ToArrayLength(&new_length));
12553 12592
12554 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); 12593 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12555 RETURN_ON_EXCEPTION( 12594 RETURN_ON_EXCEPTION(
12556 isolate, EnqueueChangeRecord(array, "add", name, 12595 isolate, EnqueueChangeRecord(array, "add", name,
12557 isolate->factory()->the_hole_value()), 12596 isolate->factory()->the_hole_value()),
12558 Object); 12597 Object);
12559 RETURN_ON_EXCEPTION(isolate, 12598 RETURN_ON_EXCEPTION(isolate,
12560 EnqueueChangeRecord(array, "update", 12599 EnqueueChangeRecord(array, "update",
12561 isolate->factory()->length_string(), 12600 isolate->factory()->length_string(),
12562 old_length_handle), 12601 old_length_handle),
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
12770 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { 12809 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
12771 Isolate* isolate = array->GetIsolate(); 12810 Isolate* isolate = array->GetIsolate();
12772 Handle<Name> length = isolate->factory()->length_string(); 12811 Handle<Name> length = isolate->factory()->length_string();
12773 THROW_NEW_ERROR( 12812 THROW_NEW_ERROR(
12774 isolate, 12813 isolate,
12775 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array), 12814 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array),
12776 Object); 12815 Object);
12777 } 12816 }
12778 12817
12779 12818
12780 bool JSObject::HasDenseElements() {
12781 int capacity = 0;
12782 int used = 0;
12783 GetElementsCapacityAndUsage(&capacity, &used);
12784 return (capacity == 0) || (used > (capacity / 2));
12785 }
12786
12787
12788 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { 12819 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
12789 *capacity = 0; 12820 *capacity = 0;
12790 *used = 0; 12821 *used = 0;
12791 12822
12792 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); 12823 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
12793 FixedArray* backing_store = NULL; 12824 FixedArray* backing_store = NULL;
12794 switch (GetElementsKind()) { 12825 switch (GetElementsKind()) {
12795 case SLOPPY_ARGUMENTS_ELEMENTS: 12826 case SLOPPY_ARGUMENTS_ELEMENTS:
12796 backing_store_base = 12827 backing_store_base =
12797 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 12828 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
12853 // External arrays are considered 100% used. 12884 // External arrays are considered 100% used.
12854 FixedArrayBase* external_array = FixedArrayBase::cast(elements()); 12885 FixedArrayBase* external_array = FixedArrayBase::cast(elements());
12855 *capacity = external_array->length(); 12886 *capacity = external_array->length();
12856 *used = external_array->length(); 12887 *used = external_array->length();
12857 break; 12888 break;
12858 } 12889 }
12859 } 12890 }
12860 } 12891 }
12861 12892
12862 12893
12863 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
12864 if (HasFastElements()) {
12865 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12866 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12867 uint32_t new_capacity;
12868 return ShouldConvertToSlowElements(capacity, index, &new_capacity);
12869 }
12870 return false;
12871 }
12872
12873
12874 bool JSObject::ShouldConvertToSlowElements(uint32_t capacity, uint32_t index,
12875 uint32_t* new_capacity) {
12876 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
12877 kMaxUncheckedFastElementsLength);
12878 if (index < capacity) {
12879 *new_capacity = capacity;
12880 return false;
12881 }
12882 if (index - capacity >= kMaxGap) return true;
12883 *new_capacity = NewElementsCapacity(index + 1);
12884 DCHECK_LT(index, *new_capacity);
12885 if (*new_capacity <= kMaxUncheckedOldFastElementsLength ||
12886 (*new_capacity <= kMaxUncheckedFastElementsLength &&
12887 GetHeap()->InNewSpace(this))) {
12888 return false;
12889 }
12890 // If the fast-case backing storage takes up roughly three times as
12891 // much space (in machine words) as a dictionary backing storage
12892 // would, the object should have slow elements.
12893 int old_capacity = 0;
12894 int used_elements = 0;
12895 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
12896 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12897 SeededNumberDictionary::kEntrySize;
12898 return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
12899 }
12900
12901
12902 ElementsKind JSObject::BestFittingFastElementsKind() {
12903 if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS;
12904 DCHECK(HasDictionaryElements());
12905 SeededNumberDictionary* dictionary = element_dictionary();
12906 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
12907 for (int i = 0; i < dictionary->Capacity(); i++) {
12908 Object* key = dictionary->KeyAt(i);
12909 if (key->IsNumber()) {
12910 Object* value = dictionary->ValueAt(i);
12911 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
12912 if (!value->IsSmi()) {
12913 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
12914 kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12915 }
12916 }
12917 }
12918 return kind;
12919 }
12920
12921
12922 // Certain compilers request function template instantiation when they 12894 // Certain compilers request function template instantiation when they
12923 // see the definition of the other template functions in the 12895 // see the definition of the other template functions in the
12924 // class. This requires us to have the template functions put 12896 // class. This requires us to have the template functions put
12925 // together, so even though this function belongs in objects-debug.cc, 12897 // together, so even though this function belongs in objects-debug.cc,
12926 // we keep it here instead to satisfy certain compilers. 12898 // we keep it here instead to satisfy certain compilers.
12927 #ifdef OBJECT_PRINT 12899 #ifdef OBJECT_PRINT
12928 template <typename Derived, typename Shape, typename Key> 12900 template <typename Derived, typename Shape, typename Key>
12929 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) { // NOLINT 12901 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) { // NOLINT
12930 int capacity = this->Capacity(); 12902 int capacity = this->Capacity();
12931 for (int i = 0; i < capacity; i++) { 12903 for (int i = 0; i < capacity; i++) {
(...skipping 3303 matching lines...) Expand 10 before | Expand all | Expand 10 after
16235 Handle<Object> new_value) { 16207 Handle<Object> new_value) {
16236 if (cell->value() != *new_value) { 16208 if (cell->value() != *new_value) {
16237 cell->set_value(*new_value); 16209 cell->set_value(*new_value);
16238 Isolate* isolate = cell->GetIsolate(); 16210 Isolate* isolate = cell->GetIsolate();
16239 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16211 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16240 isolate, DependentCode::kPropertyCellChangedGroup); 16212 isolate, DependentCode::kPropertyCellChangedGroup);
16241 } 16213 }
16242 } 16214 }
16243 } // namespace internal 16215 } // namespace internal
16244 } // namespace v8 16216 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/arguments.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698