| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 } | 166 } |
| 167 #endif | 167 #endif |
| 168 BackingStoreClass* backing_store = BackingStoreClass::cast(from); | 168 BackingStoreClass* backing_store = BackingStoreClass::cast(from); |
| 169 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); | 169 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 170 | 170 |
| 171 // Optimize if 'other' is empty. | 171 // Optimize if 'other' is empty. |
| 172 // We cannot optimize if 'this' is empty, as other may have holes. | 172 // We cannot optimize if 'this' is empty, as other may have holes. |
| 173 if (len1 == 0) return to; | 173 if (len1 == 0) return to; |
| 174 | 174 |
| 175 // Compute how many elements are not in other. | 175 // Compute how many elements are not in other. |
| 176 int extra = 0; | 176 uint32_t extra = 0; |
| 177 for (uint32_t y = 0; y < len1; y++) { | 177 for (uint32_t y = 0; y < len1; y++) { |
| 178 if (ElementsAccessorSubclass::HasElementAtIndexImpl( | 178 uint32_t key = |
| 179 backing_store, y, holder, receiver)) { | 179 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); |
| 180 uint32_t key = | 180 if (ElementsAccessorSubclass::HasElementImpl( |
| 181 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | 181 backing_store, key, holder, receiver)) { |
| 182 MaybeObject* maybe_value = | 182 MaybeObject* maybe_value = |
| 183 ElementsAccessorSubclass::GetImpl(backing_store, key, | 183 ElementsAccessorSubclass::GetImpl(backing_store, key, |
| 184 holder, receiver); | 184 holder, receiver); |
| 185 Object* value; | 185 Object* value; |
| 186 if (!maybe_value->ToObject(&value)) return maybe_value; | 186 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 187 ASSERT(!value->IsTheHole()); | 187 ASSERT(!value->IsTheHole()); |
| 188 if (!HasKey(to, value)) { | 188 if (!HasKey(to, value)) { |
| 189 extra++; | 189 extra++; |
| 190 } | 190 } |
| 191 } | 191 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 203 { | 203 { |
| 204 AssertNoAllocation no_gc; | 204 AssertNoAllocation no_gc; |
| 205 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 205 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 206 for (int i = 0; i < len0; i++) { | 206 for (int i = 0; i < len0; i++) { |
| 207 Object* e = to->get(i); | 207 Object* e = to->get(i); |
| 208 ASSERT(e->IsString() || e->IsNumber()); | 208 ASSERT(e->IsString() || e->IsNumber()); |
| 209 result->set(i, e, mode); | 209 result->set(i, e, mode); |
| 210 } | 210 } |
| 211 } | 211 } |
| 212 // Fill in the extra values. | 212 // Fill in the extra values. |
| 213 int index = 0; | 213 uint32_t index = 0; |
| 214 for (uint32_t y = 0; y < len1; y++) { | 214 for (uint32_t y = 0; y < len1; y++) { |
| 215 if (ElementsAccessorSubclass::HasElementAtIndexImpl( | 215 uint32_t key = |
| 216 backing_store, y, holder, receiver)) { | 216 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); |
| 217 uint32_t key = | 217 if (ElementsAccessorSubclass::HasElementImpl( |
| 218 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | 218 backing_store, key, holder, receiver)) { |
| 219 MaybeObject* maybe_value = | 219 MaybeObject* maybe_value = |
| 220 ElementsAccessorSubclass::GetImpl(backing_store, key, | 220 ElementsAccessorSubclass::GetImpl(backing_store, key, |
| 221 holder, receiver); | 221 holder, receiver); |
| 222 Object* value; | 222 Object* value; |
| 223 if (!maybe_value->ToObject(&value)) return maybe_value; | 223 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 224 if (!value->IsTheHole() && !HasKey(to, value)) { | 224 if (!value->IsTheHole() && !HasKey(to, value)) { |
| 225 result->set(len0 + index, value); | 225 result->set(len0 + index, value); |
| 226 index++; | 226 index++; |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 } | 229 } |
| 230 ASSERT(extra == index); | 230 ASSERT(extra == index); |
| 231 return result; | 231 return result; |
| 232 } | 232 } |
| 233 | 233 |
| 234 protected: | 234 protected: |
| 235 static uint32_t GetCapacityImpl(BackingStoreClass* backing_store) { | 235 static uint32_t GetCapacityImpl(BackingStoreClass* backing_store) { |
| 236 return backing_store->length(); | 236 return backing_store->length(); |
| 237 } | 237 } |
| 238 | 238 |
| 239 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { | 239 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { |
| 240 return ElementsAccessorSubclass::GetCapacityImpl( | 240 return ElementsAccessorSubclass::GetCapacityImpl( |
| 241 BackingStoreClass::cast(backing_store)); | 241 BackingStoreClass::cast(backing_store)); |
| 242 } | 242 } |
| 243 | 243 |
| 244 static bool HasElementAtIndexImpl(BackingStoreClass* backing_store, | 244 static bool HasElementImpl(BackingStoreClass* backing_store, |
| 245 uint32_t index, | 245 uint32_t key, |
| 246 JSObject* holder, | 246 JSObject* holder, |
| 247 Object* receiver) { | 247 Object* receiver) { |
| 248 uint32_t key = | |
| 249 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); | |
| 250 MaybeObject* element = | 248 MaybeObject* element = |
| 251 ElementsAccessorSubclass::GetImpl(backing_store, key, holder, receiver); | 249 ElementsAccessorSubclass::GetImpl(backing_store, key, holder, receiver); |
| 252 return !element->IsTheHole(); | 250 return !element->IsTheHole(); |
| 253 } | 251 } |
| 254 | 252 |
| 255 virtual bool HasElementAtIndex(FixedArrayBase* backing_store, | 253 virtual bool HasElement(FixedArrayBase* backing_store, |
| 256 uint32_t index, | 254 uint32_t key, |
| 257 JSObject* holder, | 255 JSObject* holder, |
| 258 Object* receiver) { | 256 Object* receiver) { |
| 259 return ElementsAccessorSubclass::HasElementAtIndexImpl( | 257 return ElementsAccessorSubclass::HasElementImpl( |
| 260 BackingStoreClass::cast(backing_store), index, holder, receiver); | 258 BackingStoreClass::cast(backing_store), key, holder, receiver); |
| 261 } | 259 } |
| 262 | 260 |
| 263 static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store, | 261 static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store, |
| 264 uint32_t index) { | 262 uint32_t index) { |
| 265 return index; | 263 return index; |
| 266 } | 264 } |
| 267 | 265 |
| 268 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 266 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, |
| 269 uint32_t index) { | 267 uint32_t index) { |
| 270 return ElementsAccessorSubclass::GetKeyForIndexImpl( | 268 return ElementsAccessorSubclass::GetKeyForIndexImpl( |
| 271 BackingStoreClass::cast(backing_store), index); | 269 BackingStoreClass::cast(backing_store), index); |
| 272 } | 270 } |
| 273 | 271 |
| 274 private: | 272 private: |
| 275 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 273 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 276 }; | 274 }; |
| 277 | 275 |
| 278 | 276 |
| 279 // Super class for all fast element arrays. | 277 // Super class for all fast element arrays. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 JSReceiver::DeleteMode mode) { | 432 JSReceiver::DeleteMode mode) { |
| 435 int length = obj->IsJSArray() | 433 int length = obj->IsJSArray() |
| 436 ? Smi::cast(JSArray::cast(obj)->length())->value() | 434 ? Smi::cast(JSArray::cast(obj)->length())->value() |
| 437 : FixedDoubleArray::cast(obj->elements())->length(); | 435 : FixedDoubleArray::cast(obj->elements())->length(); |
| 438 if (key < static_cast<uint32_t>(length)) { | 436 if (key < static_cast<uint32_t>(length)) { |
| 439 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); | 437 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); |
| 440 } | 438 } |
| 441 return obj->GetHeap()->true_value(); | 439 return obj->GetHeap()->true_value(); |
| 442 } | 440 } |
| 443 | 441 |
| 444 static bool HasElementAtIndexImpl(FixedDoubleArray* backing_store, | 442 static bool HasElementImpl(FixedDoubleArray* backing_store, |
| 445 uint32_t index, | 443 uint32_t key, |
| 446 JSObject* holder, | 444 JSObject* holder, |
| 447 Object* receiver) { | 445 Object* receiver) { |
| 448 return !backing_store->is_the_hole(index); | 446 return !backing_store->is_the_hole(key); |
| 449 } | 447 } |
| 450 }; | 448 }; |
| 451 | 449 |
| 452 | 450 |
| 453 // Super class for all external element arrays. | 451 // Super class for all external element arrays. |
| 454 template<typename ExternalElementsAccessorSubclass, | 452 template<typename ExternalElementsAccessorSubclass, |
| 455 typename ExternalArray> | 453 typename ExternalArray> |
| 456 class ExternalElementsAccessor | 454 class ExternalElementsAccessor |
| 457 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 455 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 458 ExternalArray> { | 456 ExternalArray> { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 477 UNREACHABLE(); | 475 UNREACHABLE(); |
| 478 return obj; | 476 return obj; |
| 479 } | 477 } |
| 480 | 478 |
| 481 virtual MaybeObject* Delete(JSObject* obj, | 479 virtual MaybeObject* Delete(JSObject* obj, |
| 482 uint32_t key, | 480 uint32_t key, |
| 483 JSReceiver::DeleteMode mode) { | 481 JSReceiver::DeleteMode mode) { |
| 484 // External arrays always ignore deletes. | 482 // External arrays always ignore deletes. |
| 485 return obj->GetHeap()->true_value(); | 483 return obj->GetHeap()->true_value(); |
| 486 } | 484 } |
| 485 |
| 486 static bool HasElementImpl(ExternalArray* backing_store, |
| 487 uint32_t key, |
| 488 JSObject* holder, |
| 489 Object* receiver) { |
| 490 uint32_t capacity = |
| 491 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 492 return key < capacity; |
| 493 } |
| 487 }; | 494 }; |
| 488 | 495 |
| 489 | 496 |
| 490 class ExternalByteElementsAccessor | 497 class ExternalByteElementsAccessor |
| 491 : public ExternalElementsAccessor<ExternalByteElementsAccessor, | 498 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
| 492 ExternalByteArray> { | 499 ExternalByteArray> { |
| 493 }; | 500 }; |
| 494 | 501 |
| 495 | 502 |
| 496 class ExternalUnsignedByteElementsAccessor | 503 class ExternalUnsignedByteElementsAccessor |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 element, | 677 element, |
| 671 key, | 678 key, |
| 672 obj); | 679 obj); |
| 673 } else { | 680 } else { |
| 674 return element; | 681 return element; |
| 675 } | 682 } |
| 676 } | 683 } |
| 677 return obj->GetHeap()->the_hole_value(); | 684 return obj->GetHeap()->the_hole_value(); |
| 678 } | 685 } |
| 679 | 686 |
| 687 static bool HasElementImpl(SeededNumberDictionary* backing_store, |
| 688 uint32_t key, |
| 689 JSObject* holder, |
| 690 Object* receiver) { |
| 691 return backing_store->FindEntry(key) != |
| 692 SeededNumberDictionary::kNotFound; |
| 693 } |
| 694 |
| 680 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, | 695 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, |
| 681 uint32_t index) { | 696 uint32_t index) { |
| 682 Object* key = dict->KeyAt(index); | 697 Object* key = dict->KeyAt(index); |
| 683 return Smi::cast(key)->value(); | 698 return Smi::cast(key)->value(); |
| 684 } | 699 } |
| 685 }; | 700 }; |
| 686 | 701 |
| 687 | 702 |
| 688 class NonStrictArgumentsElementsAccessor | 703 class NonStrictArgumentsElementsAccessor |
| 689 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 704 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 690 FixedArray> { | 705 FixedArray> { |
| 691 protected: | 706 protected: |
| 692 friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 707 friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 693 FixedArray>; | 708 FixedArray>; |
| 694 | 709 |
| 695 static MaybeObject* GetImpl(FixedArray* parameter_map, | 710 static MaybeObject* GetImpl(FixedArray* parameter_map, |
| 696 uint32_t key, | 711 uint32_t key, |
| 697 JSObject* obj, | 712 JSObject* obj, |
| 698 Object* receiver) { | 713 Object* receiver) { |
| 699 Object* probe = GetParameterMapArg(parameter_map, key); | 714 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 700 if (!probe->IsTheHole()) { | 715 if (!probe->IsTheHole()) { |
| 701 Context* context = Context::cast(parameter_map->get(0)); | 716 Context* context = Context::cast(parameter_map->get(0)); |
| 702 int context_index = Smi::cast(probe)->value(); | 717 int context_index = Smi::cast(probe)->value(); |
| 703 ASSERT(!context->get(context_index)->IsTheHole()); | 718 ASSERT(!context->get(context_index)->IsTheHole()); |
| 704 return context->get(context_index); | 719 return context->get(context_index); |
| 705 } else { | 720 } else { |
| 706 // Object is not mapped, defer to the arguments. | 721 // Object is not mapped, defer to the arguments. |
| 707 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 722 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 708 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( | 723 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( |
| 709 arguments, key, obj, receiver); | 724 arguments, key, obj, receiver); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 728 // TODO(mstarzinger): This was never implemented but will be used once we | 743 // TODO(mstarzinger): This was never implemented but will be used once we |
| 729 // correctly implement [[DefineOwnProperty]] on arrays. | 744 // correctly implement [[DefineOwnProperty]] on arrays. |
| 730 UNIMPLEMENTED(); | 745 UNIMPLEMENTED(); |
| 731 return obj; | 746 return obj; |
| 732 } | 747 } |
| 733 | 748 |
| 734 virtual MaybeObject* Delete(JSObject* obj, | 749 virtual MaybeObject* Delete(JSObject* obj, |
| 735 uint32_t key, | 750 uint32_t key, |
| 736 JSReceiver::DeleteMode mode) { | 751 JSReceiver::DeleteMode mode) { |
| 737 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 752 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| 738 Object* probe = GetParameterMapArg(parameter_map, key); | 753 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 739 if (!probe->IsTheHole()) { | 754 if (!probe->IsTheHole()) { |
| 740 // TODO(kmillikin): We could check if this was the last aliased | 755 // TODO(kmillikin): We could check if this was the last aliased |
| 741 // parameter, and revert to normal elements in that case. That | 756 // parameter, and revert to normal elements in that case. That |
| 742 // would enable GC of the context. | 757 // would enable GC of the context. |
| 743 parameter_map->set_the_hole(key + 2); | 758 parameter_map->set_the_hole(key + 2); |
| 744 } else { | 759 } else { |
| 745 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 760 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 746 if (arguments->IsDictionary()) { | 761 if (arguments->IsDictionary()) { |
| 747 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 762 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
| 748 } else { | 763 } else { |
| 749 return FastObjectElementsAccessor::DeleteCommon(obj, key); | 764 return FastObjectElementsAccessor::DeleteCommon(obj, key); |
| 750 } | 765 } |
| 751 } | 766 } |
| 752 return obj->GetHeap()->true_value(); | 767 return obj->GetHeap()->true_value(); |
| 753 } | 768 } |
| 754 | 769 |
| 755 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { | 770 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { |
| 756 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 771 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 757 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 772 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
| 758 ForArray(arguments)->GetCapacity(arguments)); | 773 ForArray(arguments)->GetCapacity(arguments)); |
| 759 } | 774 } |
| 760 | 775 |
| 761 static uint32_t GetKeyForIndexImpl(FixedArray* dict, | 776 static uint32_t GetKeyForIndexImpl(FixedArray* dict, |
| 762 uint32_t index) { | 777 uint32_t index) { |
| 763 return index; | 778 return index; |
| 764 } | 779 } |
| 765 | 780 |
| 766 static bool HasElementAtIndexImpl(FixedArray* parameter_map, | 781 static bool HasElementImpl(FixedArray* parameter_map, |
| 767 uint32_t index, | 782 uint32_t key, |
| 768 JSObject* holder, | 783 JSObject* holder, |
| 769 Object* receiver) { | 784 Object* receiver) { |
| 770 Object* probe = GetParameterMapArg(parameter_map, index); | 785 Object* probe = GetParameterMapArg(holder, parameter_map, key); |
| 771 if (!probe->IsTheHole()) { | 786 if (!probe->IsTheHole()) { |
| 772 return true; | 787 return true; |
| 773 } else { | 788 } else { |
| 774 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 789 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 775 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | 790 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
| 776 return !accessor->Get(arguments, index, holder, receiver)->IsTheHole(); | 791 return !accessor->Get(arguments, key, holder, receiver)->IsTheHole(); |
| 777 } | 792 } |
| 778 } | 793 } |
| 779 | 794 |
| 780 private: | 795 private: |
| 781 static Object* GetParameterMapArg(FixedArray* parameter_map, | 796 static Object* GetParameterMapArg(JSObject* holder, |
| 797 FixedArray* parameter_map, |
| 782 uint32_t key) { | 798 uint32_t key) { |
| 783 uint32_t length = parameter_map->length(); | 799 uint32_t length = holder->IsJSArray() |
| 800 ? Smi::cast(JSArray::cast(holder)->length())->value() |
| 801 : parameter_map->length(); |
| 784 return key < (length - 2 ) | 802 return key < (length - 2 ) |
| 785 ? parameter_map->get(key + 2) | 803 ? parameter_map->get(key + 2) |
| 786 : parameter_map->GetHeap()->the_hole_value(); | 804 : parameter_map->GetHeap()->the_hole_value(); |
| 787 } | 805 } |
| 788 }; | 806 }; |
| 789 | 807 |
| 790 | 808 |
| 791 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 809 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
| 792 switch (array->map()->instance_type()) { | 810 switch (array->map()->instance_type()) { |
| 793 case FIXED_ARRAY_TYPE: | 811 case FIXED_ARRAY_TYPE: |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 940 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
| 923 new_backing_store->set(0, length); | 941 new_backing_store->set(0, length); |
| 924 { MaybeObject* result = array->SetContent(new_backing_store); | 942 { MaybeObject* result = array->SetContent(new_backing_store); |
| 925 if (result->IsFailure()) return result; | 943 if (result->IsFailure()) return result; |
| 926 } | 944 } |
| 927 return array; | 945 return array; |
| 928 } | 946 } |
| 929 | 947 |
| 930 | 948 |
| 931 } } // namespace v8::internal | 949 } } // namespace v8::internal |
| OLD | NEW |