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

Side by Side Diff: src/objects.cc

Issue 2870018: Add "has fast elements" bit to maps and use it in inlined keyed loads. (Closed)
Patch Set: More ARM fixes. Created 10 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') | src/objects-debug.cc » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2204 matching lines...) Expand 10 before | Expand all | Expand 10 after
2215 if (HasFastProperties()) return this; 2215 if (HasFastProperties()) return this;
2216 ASSERT(!IsGlobalObject()); 2216 ASSERT(!IsGlobalObject());
2217 return property_dictionary()-> 2217 return property_dictionary()->
2218 TransformPropertiesToFastFor(this, unused_property_fields); 2218 TransformPropertiesToFastFor(this, unused_property_fields);
2219 } 2219 }
2220 2220
2221 2221
2222 Object* JSObject::NormalizeElements() { 2222 Object* JSObject::NormalizeElements() {
2223 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); 2223 ASSERT(!HasPixelElements() && !HasExternalArrayElements());
2224 if (HasDictionaryElements()) return this; 2224 if (HasDictionaryElements()) return this;
2225 ASSERT(map()->has_fast_elements());
2226
2227 Object* obj = map()->GetSlowElementsMap();
2228 if (obj->IsFailure()) return obj;
2229 Map* new_map = Map::cast(obj);
2225 2230
2226 // Get number of entries. 2231 // Get number of entries.
2227 FixedArray* array = FixedArray::cast(elements()); 2232 FixedArray* array = FixedArray::cast(elements());
2228 2233
2229 // Compute the effective length. 2234 // Compute the effective length.
2230 int length = IsJSArray() ? 2235 int length = IsJSArray() ?
2231 Smi::cast(JSArray::cast(this)->length())->value() : 2236 Smi::cast(JSArray::cast(this)->length())->value() :
2232 array->length(); 2237 array->length();
2233 Object* obj = NumberDictionary::Allocate(length); 2238 obj = NumberDictionary::Allocate(length);
2234 if (obj->IsFailure()) return obj; 2239 if (obj->IsFailure()) return obj;
2235 NumberDictionary* dictionary = NumberDictionary::cast(obj); 2240 NumberDictionary* dictionary = NumberDictionary::cast(obj);
2236 // Copy entries. 2241 // Copy entries.
2237 for (int i = 0; i < length; i++) { 2242 for (int i = 0; i < length; i++) {
2238 Object* value = array->get(i); 2243 Object* value = array->get(i);
2239 if (!value->IsTheHole()) { 2244 if (!value->IsTheHole()) {
2240 PropertyDetails details = PropertyDetails(NONE, NORMAL); 2245 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2241 Object* result = dictionary->AddNumberEntry(i, array->get(i), details); 2246 Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
2242 if (result->IsFailure()) return result; 2247 if (result->IsFailure()) return result;
2243 dictionary = NumberDictionary::cast(result); 2248 dictionary = NumberDictionary::cast(result);
2244 } 2249 }
2245 } 2250 }
2246 // Switch to using the dictionary as the backing storage for elements. 2251 // Switch to using the dictionary as the backing storage for
2252 // elements. Set the new map first to satify the elements type
2253 // assert in set_elements().
2254 set_map(new_map);
2247 set_elements(dictionary); 2255 set_elements(dictionary);
2248 2256
2249 Counters::elements_to_dictionary.Increment(); 2257 Counters::elements_to_dictionary.Increment();
2250 2258
2251 #ifdef DEBUG 2259 #ifdef DEBUG
2252 if (FLAG_trace_normalization) { 2260 if (FLAG_trace_normalization) {
2253 PrintF("Object elements have been normalized:\n"); 2261 PrintF("Object elements have been normalized:\n");
2254 Print(); 2262 Print();
2255 } 2263 }
2256 #endif 2264 #endif
(...skipping 3209 matching lines...) Expand 10 before | Expand all | Expand 10 after
5466 PrintF("\n"); 5474 PrintF("\n");
5467 5475
5468 PrintF("RelocInfo (size = %d)\n", relocation_size()); 5476 PrintF("RelocInfo (size = %d)\n", relocation_size());
5469 for (RelocIterator it(this); !it.done(); it.next()) 5477 for (RelocIterator it(this); !it.done(); it.next())
5470 it.rinfo()->Print(); 5478 it.rinfo()->Print();
5471 PrintF("\n"); 5479 PrintF("\n");
5472 } 5480 }
5473 #endif // ENABLE_DISASSEMBLER 5481 #endif // ENABLE_DISASSEMBLER
5474 5482
5475 5483
5476 void JSObject::SetFastElements(FixedArray* elems) { 5484 Object* JSObject::SetFastElementsCapacityAndLength(int capacity, int length) {
5477 // We should never end in here with a pixel or external array. 5485 // We should never end in here with a pixel or external array.
5478 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); 5486 ASSERT(!HasPixelElements() && !HasExternalArrayElements());
5479 #ifdef DEBUG 5487
5480 // Check the provided array is filled with the_hole. 5488 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
5481 uint32_t len = static_cast<uint32_t>(elems->length()); 5489 if (obj->IsFailure()) return obj;
5482 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); 5490 FixedArray* elems = FixedArray::cast(obj);
5483 #endif 5491
5492 obj = map()->GetFastElementsMap();
5493 if (obj->IsFailure()) return obj;
5494 Map* new_map = Map::cast(obj);
5495
5484 AssertNoAllocation no_gc; 5496 AssertNoAllocation no_gc;
5485 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); 5497 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
5486 switch (GetElementsKind()) { 5498 switch (GetElementsKind()) {
5487 case FAST_ELEMENTS: { 5499 case FAST_ELEMENTS: {
5488 FixedArray* old_elements = FixedArray::cast(elements()); 5500 FixedArray* old_elements = FixedArray::cast(elements());
5489 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 5501 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
5490 // Fill out the new array with this content and array holes. 5502 // Fill out the new array with this content and array holes.
5491 for (uint32_t i = 0; i < old_length; i++) { 5503 for (uint32_t i = 0; i < old_length; i++) {
5492 elems->set(i, old_elements->get(i), mode); 5504 elems->set(i, old_elements->get(i), mode);
5493 } 5505 }
5494 break; 5506 break;
5495 } 5507 }
5496 case DICTIONARY_ELEMENTS: { 5508 case DICTIONARY_ELEMENTS: {
5497 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 5509 NumberDictionary* dictionary = NumberDictionary::cast(elements());
5498 for (int i = 0; i < dictionary->Capacity(); i++) { 5510 for (int i = 0; i < dictionary->Capacity(); i++) {
5499 Object* key = dictionary->KeyAt(i); 5511 Object* key = dictionary->KeyAt(i);
5500 if (key->IsNumber()) { 5512 if (key->IsNumber()) {
5501 uint32_t entry = static_cast<uint32_t>(key->Number()); 5513 uint32_t entry = static_cast<uint32_t>(key->Number());
5502 elems->set(entry, dictionary->ValueAt(i), mode); 5514 elems->set(entry, dictionary->ValueAt(i), mode);
5503 } 5515 }
5504 } 5516 }
5505 break; 5517 break;
5506 } 5518 }
5507 default: 5519 default:
5508 UNREACHABLE(); 5520 UNREACHABLE();
5509 break; 5521 break;
5510 } 5522 }
5523
5524 set_map(new_map);
5511 set_elements(elems); 5525 set_elements(elems);
5526
5527 if (IsJSArray()) {
5528 JSArray::cast(this)->set_length(Smi::FromInt(length));
5529 }
5530
5531 return this;
5512 } 5532 }
5513 5533
5514 5534
5515 Object* JSObject::SetSlowElements(Object* len) { 5535 Object* JSObject::SetSlowElements(Object* len) {
5516 // We should never end in here with a pixel or external array. 5536 // We should never end in here with a pixel or external array.
5517 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); 5537 ASSERT(!HasPixelElements() && !HasExternalArrayElements());
5518 5538
5519 uint32_t new_length = static_cast<uint32_t>(len->Number()); 5539 uint32_t new_length = static_cast<uint32_t>(len->Number());
5520 5540
5521 switch (GetElementsKind()) { 5541 switch (GetElementsKind()) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5588 HandleVector<Object>(NULL, 0))); 5608 HandleVector<Object>(NULL, 0)));
5589 } 5609 }
5590 5610
5591 5611
5592 Object* JSObject::SetElementsLength(Object* len) { 5612 Object* JSObject::SetElementsLength(Object* len) {
5593 // We should never end in here with a pixel or external array. 5613 // We should never end in here with a pixel or external array.
5594 ASSERT(AllowsSetElementsLength()); 5614 ASSERT(AllowsSetElementsLength());
5595 5615
5596 Object* smi_length = len->ToSmi(); 5616 Object* smi_length = len->ToSmi();
5597 if (smi_length->IsSmi()) { 5617 if (smi_length->IsSmi()) {
5598 int value = Smi::cast(smi_length)->value(); 5618 const int value = Smi::cast(smi_length)->value();
5599 if (value < 0) return ArrayLengthRangeError(); 5619 if (value < 0) return ArrayLengthRangeError();
5600 switch (GetElementsKind()) { 5620 switch (GetElementsKind()) {
5601 case FAST_ELEMENTS: { 5621 case FAST_ELEMENTS: {
5602 int old_capacity = FixedArray::cast(elements())->length(); 5622 int old_capacity = FixedArray::cast(elements())->length();
5603 if (value <= old_capacity) { 5623 if (value <= old_capacity) {
5604 if (IsJSArray()) { 5624 if (IsJSArray()) {
5605 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); 5625 int old_length = FastD2I(JSArray::cast(this)->length()->Number());
5606 // NOTE: We may be able to optimize this by removing the 5626 // NOTE: We may be able to optimize this by removing the
5607 // last part of the elements backing storage array and 5627 // last part of the elements backing storage array and
5608 // setting the capacity to the new size. 5628 // setting the capacity to the new size.
5609 for (int i = value; i < old_length; i++) { 5629 for (int i = value; i < old_length; i++) {
5610 FixedArray::cast(elements())->set_the_hole(i); 5630 FixedArray::cast(elements())->set_the_hole(i);
5611 } 5631 }
5612 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 5632 JSArray::cast(this)->set_length(Smi::cast(smi_length));
5613 } 5633 }
5614 return this; 5634 return this;
5615 } 5635 }
5616 int min = NewElementsCapacity(old_capacity); 5636 int min = NewElementsCapacity(old_capacity);
5617 int new_capacity = value > min ? value : min; 5637 int new_capacity = value > min ? value : min;
5618 if (new_capacity <= kMaxFastElementsLength || 5638 if (new_capacity <= kMaxFastElementsLength ||
5619 !ShouldConvertToSlowElements(new_capacity)) { 5639 !ShouldConvertToSlowElements(new_capacity)) {
5620 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); 5640 Object* obj = SetFastElementsCapacityAndLength(new_capacity, value);
5621 if (obj->IsFailure()) return obj; 5641 if (obj->IsFailure()) return obj;
5622 if (IsJSArray()) {
5623 JSArray::cast(this)->set_length(Smi::cast(smi_length));
5624 }
5625 SetFastElements(FixedArray::cast(obj));
5626 return this; 5642 return this;
5627 } 5643 }
5628 break; 5644 break;
5629 } 5645 }
5630 case DICTIONARY_ELEMENTS: { 5646 case DICTIONARY_ELEMENTS: {
5631 if (IsJSArray()) { 5647 if (IsJSArray()) {
5632 if (value == 0) { 5648 if (value == 0) {
5633 // If the length of a slow array is reset to zero, we clear 5649 // If the length of a slow array is reset to zero, we clear
5634 // the array and flush backing storage. This has the added 5650 // the array and flush backing storage. This has the added
5635 // benefit that the array returns to fast mode. 5651 // benefit that the array returns to fast mode.
5636 initialize_elements(); 5652 Object* obj = ResetElements();
5653 if (obj->IsFailure()) return obj;
5637 } else { 5654 } else {
5638 // Remove deleted elements. 5655 // Remove deleted elements.
5639 uint32_t old_length = 5656 uint32_t old_length =
5640 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 5657 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5641 element_dictionary()->RemoveNumberEntries(value, old_length); 5658 element_dictionary()->RemoveNumberEntries(value, old_length);
5642 } 5659 }
5643 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 5660 JSArray::cast(this)->set_length(Smi::cast(smi_length));
5644 } 5661 }
5645 return this; 5662 return this;
5646 } 5663 }
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
6085 return value; 6102 return value;
6086 } 6103 }
6087 6104
6088 // Allow gap in fast case. 6105 // Allow gap in fast case.
6089 if ((index - elms_length) < kMaxGap) { 6106 if ((index - elms_length) < kMaxGap) {
6090 // Try allocating extra space. 6107 // Try allocating extra space.
6091 int new_capacity = NewElementsCapacity(index+1); 6108 int new_capacity = NewElementsCapacity(index+1);
6092 if (new_capacity <= kMaxFastElementsLength || 6109 if (new_capacity <= kMaxFastElementsLength ||
6093 !ShouldConvertToSlowElements(new_capacity)) { 6110 !ShouldConvertToSlowElements(new_capacity)) {
6094 ASSERT(static_cast<uint32_t>(new_capacity) > index); 6111 ASSERT(static_cast<uint32_t>(new_capacity) > index);
6095 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); 6112 Object* obj = SetFastElementsCapacityAndLength(new_capacity, index + 1);
6096 if (obj->IsFailure()) return obj; 6113 if (obj->IsFailure()) return obj;
6097 SetFastElements(FixedArray::cast(obj));
6098 if (IsJSArray()) {
6099 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
6100 }
6101 FixedArray::cast(elements())->set(index, value); 6114 FixedArray::cast(elements())->set(index, value);
6102 return value; 6115 return value;
6103 } 6116 }
6104 } 6117 }
6105 6118
6106 // Otherwise default to slow case. 6119 // Otherwise default to slow case.
6107 Object* obj = NormalizeElements(); 6120 Object* obj = NormalizeElements();
6108 if (obj->IsFailure()) return obj; 6121 if (obj->IsFailure()) return obj;
6109 ASSERT(HasDictionaryElements()); 6122 ASSERT(HasDictionaryElements());
6110 return SetElement(index, value); 6123 return SetElement(index, value);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
6209 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, 6222 Object* return_value = array->JSArrayUpdateLengthFromIndex(index,
6210 value); 6223 value);
6211 if (return_value->IsFailure()) return return_value; 6224 if (return_value->IsFailure()) return return_value;
6212 } 6225 }
6213 6226
6214 // Attempt to put this object back in fast case. 6227 // Attempt to put this object back in fast case.
6215 if (ShouldConvertToFastElements()) { 6228 if (ShouldConvertToFastElements()) {
6216 uint32_t new_length = 0; 6229 uint32_t new_length = 0;
6217 if (IsJSArray()) { 6230 if (IsJSArray()) {
6218 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 6231 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
6219 JSArray::cast(this)->set_length(Smi::FromInt(new_length));
6220 } else { 6232 } else {
6221 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; 6233 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
6222 } 6234 }
6223 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); 6235 Object* obj = SetFastElementsCapacityAndLength(new_length, new_length);
6224 if (obj->IsFailure()) return obj; 6236 if (obj->IsFailure()) return obj;
6225 SetFastElements(FixedArray::cast(obj));
6226 #ifdef DEBUG 6237 #ifdef DEBUG
6227 if (FLAG_trace_normalization) { 6238 if (FLAG_trace_normalization) {
6228 PrintF("Object elements are fast case again:\n"); 6239 PrintF("Object elements are fast case again:\n");
6229 Print(); 6240 Print();
6230 } 6241 }
6231 #endif 6242 #endif
6232 } 6243 }
6233 6244
6234 return value; 6245 return value;
6235 } 6246 }
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after
7519 if (HasDictionaryElements()) { 7530 if (HasDictionaryElements()) {
7520 // Convert to fast elements containing only the existing properties. 7531 // Convert to fast elements containing only the existing properties.
7521 // Ordering is irrelevant, since we are going to sort anyway. 7532 // Ordering is irrelevant, since we are going to sort anyway.
7522 NumberDictionary* dict = element_dictionary(); 7533 NumberDictionary* dict = element_dictionary();
7523 if (IsJSArray() || dict->requires_slow_elements() || 7534 if (IsJSArray() || dict->requires_slow_elements() ||
7524 dict->max_number_key() >= limit) { 7535 dict->max_number_key() >= limit) {
7525 return PrepareSlowElementsForSort(limit); 7536 return PrepareSlowElementsForSort(limit);
7526 } 7537 }
7527 // Convert to fast elements. 7538 // Convert to fast elements.
7528 7539
7540 Object* obj = map()->GetFastElementsMap();
7541 if (obj->IsFailure()) return obj;
7542 Map* new_map = Map::cast(obj);
7543
7529 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; 7544 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
7530 Object* new_array = 7545 Object* new_array =
7531 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); 7546 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
7532 if (new_array->IsFailure()) { 7547 if (new_array->IsFailure()) return new_array;
7533 return new_array;
7534 }
7535 FixedArray* fast_elements = FixedArray::cast(new_array); 7548 FixedArray* fast_elements = FixedArray::cast(new_array);
7536 dict->CopyValuesTo(fast_elements); 7549 dict->CopyValuesTo(fast_elements);
7550
7551 set_map(new_map);
7537 set_elements(fast_elements); 7552 set_elements(fast_elements);
7538 } 7553 }
7539 ASSERT(HasFastElements()); 7554 ASSERT(HasFastElements());
7540 7555
7541 // Collect holes at the end, undefined before that and the rest at the 7556 // Collect holes at the end, undefined before that and the rest at the
7542 // start, and return the number of non-hole, non-undefined values. 7557 // start, and return the number of non-hole, non-undefined values.
7543 7558
7544 FixedArray* elements = FixedArray::cast(this->elements()); 7559 FixedArray* elements = FixedArray::cast(this->elements());
7545 uint32_t elements_length = static_cast<uint32_t>(elements->length()); 7560 uint32_t elements_length = static_cast<uint32_t>(elements->length());
7546 if (limit > elements_length) { 7561 if (limit > elements_length) {
(...skipping 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after
8723 if (break_point_objects()->IsUndefined()) return 0; 8738 if (break_point_objects()->IsUndefined()) return 0;
8724 // Single beak point. 8739 // Single beak point.
8725 if (!break_point_objects()->IsFixedArray()) return 1; 8740 if (!break_point_objects()->IsFixedArray()) return 1;
8726 // Multiple break points. 8741 // Multiple break points.
8727 return FixedArray::cast(break_point_objects())->length(); 8742 return FixedArray::cast(break_point_objects())->length();
8728 } 8743 }
8729 #endif 8744 #endif
8730 8745
8731 8746
8732 } } // namespace v8::internal 8747 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698