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 |