| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 19 matching lines...) Expand all Loading... |
| 30 #include "objects.h" | 30 #include "objects.h" |
| 31 #include "elements.h" | 31 #include "elements.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 | 36 |
| 37 ElementsAccessor** ElementsAccessor::elements_accessors_; | 37 ElementsAccessor** ElementsAccessor::elements_accessors_; |
| 38 | 38 |
| 39 | 39 |
| 40 bool HasKey(FixedArray* array, Object* key) { |
| 41 int len0 = array->length(); |
| 42 for (int i = 0; i < len0; i++) { |
| 43 Object* element = array->get(i); |
| 44 if (element->IsSmi() && element == key) return true; |
| 45 if (element->IsString() && |
| 46 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
| 47 return true; |
| 48 } |
| 49 } |
| 50 return false; |
| 51 } |
| 52 |
| 53 |
| 40 // Base class for element handler implementations. Contains the | 54 // Base class for element handler implementations. Contains the |
| 41 // the common logic for objects with different ElementsKinds. | 55 // the common logic for objects with different ElementsKinds. |
| 42 // Subclasses must specialize method for which the element | 56 // Subclasses must specialize method for which the element |
| 43 // implementation differs from the base class implementation. | 57 // implementation differs from the base class implementation. |
| 44 // | 58 // |
| 45 // This class is intended to be used in the following way: | 59 // This class is intended to be used in the following way: |
| 46 // | 60 // |
| 47 // class SomeElementsAccessor : | 61 // class SomeElementsAccessor : |
| 48 // public ElementsAccessorBase<SomeElementsAccessor, | 62 // public ElementsAccessorBase<SomeElementsAccessor, |
| 49 // BackingStoreClass> { | 63 // BackingStoreClass> { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 66 ElementsAccessorSubclass::GetBackingStore(obj); | 80 ElementsAccessorSubclass::GetBackingStore(obj); |
| 67 return backing_store->get(index); | 81 return backing_store->get(index); |
| 68 } | 82 } |
| 69 return obj->GetHeap()->the_hole_value(); | 83 return obj->GetHeap()->the_hole_value(); |
| 70 } | 84 } |
| 71 | 85 |
| 72 virtual MaybeObject* Delete(JSObject* obj, | 86 virtual MaybeObject* Delete(JSObject* obj, |
| 73 uint32_t index, | 87 uint32_t index, |
| 74 JSReceiver::DeleteMode mode) = 0; | 88 JSReceiver::DeleteMode mode) = 0; |
| 75 | 89 |
| 90 virtual MaybeObject* AddJSArrayKeysToFixedArray(JSArray* other, |
| 91 FixedArray* keys) { |
| 92 int len0 = keys->length(); |
| 93 #ifdef DEBUG |
| 94 if (FLAG_enable_slow_asserts) { |
| 95 for (int i = 0; i < len0; i++) { |
| 96 ASSERT(keys->get(i)->IsString() || keys->get(i)->IsNumber()); |
| 97 } |
| 98 } |
| 99 #endif |
| 100 int len1 = ElementsAccessorSubclass::GetCapacity(other); |
| 101 |
| 102 // Optimize if 'other' is empty. |
| 103 // We cannot optimize if 'this' is empty, as other may have holes |
| 104 // or non keys. |
| 105 if (len1 == 0) return keys; |
| 106 |
| 107 // Compute how many elements are not in other. |
| 108 int extra = 0; |
| 109 for (int y = 0; y < len1; y++) { |
| 110 Object* value; |
| 111 MaybeObject* maybe_value = |
| 112 ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y); |
| 113 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 114 if (!value->IsTheHole() && !HasKey(keys, value)) extra++; |
| 115 } |
| 116 |
| 117 if (extra == 0) return keys; |
| 118 |
| 119 // Allocate the result |
| 120 FixedArray* result; |
| 121 MaybeObject* maybe_obj = |
| 122 other->GetHeap()->AllocateFixedArray(len0 + extra); |
| 123 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; |
| 124 |
| 125 // Fill in the content |
| 126 { |
| 127 AssertNoAllocation no_gc; |
| 128 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 129 for (int i = 0; i < len0; i++) { |
| 130 Object* e = keys->get(i); |
| 131 ASSERT(e->IsString() || e->IsNumber()); |
| 132 result->set(i, e, mode); |
| 133 } |
| 134 } |
| 135 // Fill in the extra keys. |
| 136 int index = 0; |
| 137 for (int y = 0; y < len1; y++) { |
| 138 MaybeObject* maybe_value = |
| 139 ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y); |
| 140 Object* value; |
| 141 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 142 if (!value->IsTheHole() && !HasKey(keys, value)) { |
| 143 ASSERT(value->IsString() || value->IsNumber()); |
| 144 result->set(len0 + index, value); |
| 145 index++; |
| 146 } |
| 147 } |
| 148 ASSERT(extra == index); |
| 149 return result; |
| 150 } |
| 151 |
| 152 static uint32_t GetCapacity(JSObject* obj) { |
| 153 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); |
| 154 } |
| 155 |
| 156 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { |
| 157 BackingStoreClass* backing_store = |
| 158 ElementsAccessorSubclass::GetBackingStore(obj); |
| 159 return backing_store->get(index); |
| 160 } |
| 161 |
| 76 protected: | 162 protected: |
| 77 static BackingStoreClass* GetBackingStore(JSObject* obj) { | 163 static BackingStoreClass* GetBackingStore(JSObject* obj) { |
| 78 return BackingStoreClass::cast(obj->elements()); | 164 return BackingStoreClass::cast(obj->elements()); |
| 79 } | 165 } |
| 80 | 166 |
| 81 static uint32_t GetLength(JSObject* obj) { | 167 static uint32_t GetLength(JSObject* obj) { |
| 82 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | 168 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); |
| 83 } | 169 } |
| 84 | 170 |
| 85 private: | 171 private: |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 404 } |
| 319 | 405 |
| 320 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 406 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 321 Object* receiver, | 407 Object* receiver, |
| 322 uint32_t index) { | 408 uint32_t index) { |
| 323 return GetNumberDictionaryElement(obj, | 409 return GetNumberDictionaryElement(obj, |
| 324 receiver, | 410 receiver, |
| 325 obj->element_dictionary(), | 411 obj->element_dictionary(), |
| 326 index); | 412 index); |
| 327 } | 413 } |
| 414 |
| 415 static uint32_t GetCapacity(JSObject* obj) { |
| 416 return obj->element_dictionary()->Capacity(); |
| 417 } |
| 418 |
| 419 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { |
| 420 NumberDictionary* dict = obj->element_dictionary(); |
| 421 if (dict->IsKey(dict->KeyAt(index))) { |
| 422 return dict->ValueAt(index); |
| 423 } else { |
| 424 return obj->GetHeap()->the_hole_value(); |
| 425 } |
| 426 } |
| 328 }; | 427 }; |
| 329 | 428 |
| 330 | 429 |
| 331 class NonStrictArgumentsElementsAccessor | 430 class NonStrictArgumentsElementsAccessor |
| 332 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 431 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 333 FixedArray> { | 432 FixedArray> { |
| 334 public: | 433 public: |
| 335 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 434 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 336 Object* receiver, | 435 Object* receiver, |
| 337 uint32_t index) { | 436 uint32_t index) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 } else { | 474 } else { |
| 376 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 475 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 377 if (arguments->IsDictionary()) { | 476 if (arguments->IsDictionary()) { |
| 378 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); | 477 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); |
| 379 } else { | 478 } else { |
| 380 return FastElementsAccessor::DeleteCommon(obj, index); | 479 return FastElementsAccessor::DeleteCommon(obj, index); |
| 381 } | 480 } |
| 382 } | 481 } |
| 383 return obj->GetHeap()->true_value(); | 482 return obj->GetHeap()->true_value(); |
| 384 } | 483 } |
| 484 |
| 485 static uint32_t GetCapacity(JSObject* obj) { |
| 486 // TODO(danno): Return max of parameter map length or backing store |
| 487 // capacity. |
| 488 return 0; |
| 489 } |
| 490 |
| 491 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { |
| 492 // TODO(danno): Return either value from parameter map of backing |
| 493 // store value at index. |
| 494 return obj->GetHeap()->the_hole_value(); |
| 495 } |
| 385 }; | 496 }; |
| 386 | 497 |
| 387 | 498 |
| 388 void ElementsAccessor::InitializeOncePerProcess() { | 499 void ElementsAccessor::InitializeOncePerProcess() { |
| 389 static struct ConcreteElementsAccessors { | 500 static struct ConcreteElementsAccessors { |
| 390 FastElementsAccessor fast_elements_handler; | 501 FastElementsAccessor fast_elements_handler; |
| 391 FastDoubleElementsAccessor fast_double_elements_handler; | 502 FastDoubleElementsAccessor fast_double_elements_handler; |
| 392 DictionaryElementsAccessor dictionary_elements_handler; | 503 DictionaryElementsAccessor dictionary_elements_handler; |
| 393 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; | 504 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; |
| 394 ExternalByteElementsAccessor byte_elements_handler; | 505 ExternalByteElementsAccessor byte_elements_handler; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 416 &element_accessors.float_elements_handler, | 527 &element_accessors.float_elements_handler, |
| 417 &element_accessors.double_elements_handler, | 528 &element_accessors.double_elements_handler, |
| 418 &element_accessors.pixel_elements_handler | 529 &element_accessors.pixel_elements_handler |
| 419 }; | 530 }; |
| 420 | 531 |
| 421 elements_accessors_ = accessor_array; | 532 elements_accessors_ = accessor_array; |
| 422 } | 533 } |
| 423 | 534 |
| 424 | 535 |
| 425 } } // namespace v8::internal | 536 } } // namespace v8::internal |
| OLD | NEW |