Chromium Code Reviews| 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() && key->IsSmi() && (element == key)) return true; | |
|
Kevin Millikin (Chromium)
2011/08/09 14:46:55
If you feel like it, you could write
if (element-
danno
2011/08/09 16:38:40
Done.
| |
| 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 this. | |
|
Kevin Millikin (Chromium)
2011/08/09 14:46:55
"not in other".
danno
2011/08/09 16:38:40
Done.
| |
| 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 Object* obj; | |
|
Kevin Millikin (Chromium)
2011/08/09 14:46:55
There's a template member function on MaybeObject
danno
2011/08/09 16:38:40
Done.
| |
| 121 { MaybeObject* maybe_obj = | |
| 122 other->GetHeap()->AllocateFixedArray(len0 + extra); | |
| 123 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 124 } | |
| 125 // Fill in the content | |
| 126 FixedArray* result = FixedArray::cast(obj); | |
| 127 { | |
| 128 AssertNoAllocation no_gc; | |
| 129 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | |
| 130 for (int i = 0; i < len0; i++) { | |
| 131 Object* e = keys->get(i); | |
| 132 ASSERT(e->IsString() || e->IsNumber()); | |
| 133 result->set(i, e, mode); | |
| 134 } | |
| 135 } | |
| 136 // Fill in the extra keys. | |
| 137 int index = 0; | |
| 138 for (int y = 0; y < len1; y++) { | |
| 139 MaybeObject* maybe_value = | |
| 140 ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y); | |
| 141 Object* value; | |
| 142 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 143 if (!value->IsTheHole() && !HasKey(keys, value)) { | |
| 144 ASSERT(value->IsString() || value->IsNumber()); | |
| 145 result->set(len0 + index, value); | |
| 146 index++; | |
| 147 } | |
| 148 } | |
| 149 ASSERT(extra == index); | |
| 150 return result; | |
| 151 } | |
| 152 | |
| 153 static uint32_t GetCapacity(JSObject* obj) { | |
| 154 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | |
| 155 } | |
| 156 | |
| 157 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, | |
| 158 int index) { | |
|
Kevin Millikin (Chromium)
2011/08/09 14:46:55
Indentation is off here.
danno
2011/08/09 16:38:40
Done.
| |
| 159 BackingStoreClass* backing_store = | |
| 160 ElementsAccessorSubclass::GetBackingStore(obj); | |
| 161 return backing_store->get(index); | |
| 162 } | |
| 163 | |
| 76 protected: | 164 protected: |
| 77 static BackingStoreClass* GetBackingStore(JSObject* obj) { | 165 static BackingStoreClass* GetBackingStore(JSObject* obj) { |
| 78 return BackingStoreClass::cast(obj->elements()); | 166 return BackingStoreClass::cast(obj->elements()); |
| 79 } | 167 } |
| 80 | 168 |
| 81 static uint32_t GetLength(JSObject* obj) { | 169 static uint32_t GetLength(JSObject* obj) { |
| 82 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | 170 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); |
| 83 } | 171 } |
| 84 | 172 |
| 85 private: | 173 private: |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 } | 406 } |
| 319 | 407 |
| 320 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 408 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 321 Object* receiver, | 409 Object* receiver, |
| 322 uint32_t index) { | 410 uint32_t index) { |
| 323 return GetNumberDictionaryElement(obj, | 411 return GetNumberDictionaryElement(obj, |
| 324 receiver, | 412 receiver, |
| 325 obj->element_dictionary(), | 413 obj->element_dictionary(), |
| 326 index); | 414 index); |
| 327 } | 415 } |
| 416 | |
| 417 static uint32_t GetCapacity(JSObject* obj) { | |
| 418 return obj->element_dictionary()->Capacity(); | |
| 419 } | |
| 420 | |
| 421 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, | |
| 422 int index) { | |
|
Kevin Millikin (Chromium)
2011/08/09 14:46:55
Indentation is off here.
danno
2011/08/09 16:38:40
Done.
| |
| 423 NumberDictionary* dict = obj->element_dictionary(); | |
| 424 if (dict->IsKey(dict->KeyAt(index))) { | |
| 425 return dict->ValueAt(index); | |
| 426 } else { | |
| 427 return obj->GetHeap()->the_hole_value(); | |
| 428 } | |
| 429 } | |
| 328 }; | 430 }; |
| 329 | 431 |
| 330 | 432 |
| 331 class NonStrictArgumentsElementsAccessor | 433 class NonStrictArgumentsElementsAccessor |
| 332 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 434 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 333 FixedArray> { | 435 FixedArray> { |
| 334 public: | 436 public: |
| 335 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 437 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 336 Object* receiver, | 438 Object* receiver, |
| 337 uint32_t index) { | 439 uint32_t index) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 } else { | 477 } else { |
| 376 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 478 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 377 if (arguments->IsDictionary()) { | 479 if (arguments->IsDictionary()) { |
| 378 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); | 480 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); |
| 379 } else { | 481 } else { |
| 380 return FastElementsAccessor::DeleteCommon(obj, index); | 482 return FastElementsAccessor::DeleteCommon(obj, index); |
| 381 } | 483 } |
| 382 } | 484 } |
| 383 return obj->GetHeap()->true_value(); | 485 return obj->GetHeap()->true_value(); |
| 384 } | 486 } |
| 487 | |
| 488 static uint32_t GetCapacity(JSObject* obj) { | |
| 489 // TODO(danno): Return max of parameter map length or backing store | |
| 490 // capacity. | |
| 491 return 0; | |
| 492 } | |
| 493 | |
| 494 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | |
| 495 // TODO(danno): Return either value from parameter map of backing | |
| 496 // store value at index. | |
| 497 return obj->GetHeap()->the_hole_value(); | |
| 498 } | |
| 385 }; | 499 }; |
| 386 | 500 |
| 387 | 501 |
| 388 void ElementsAccessor::InitializeOncePerProcess() { | 502 void ElementsAccessor::InitializeOncePerProcess() { |
| 389 static struct ConcreteElementsAccessors { | 503 static struct ConcreteElementsAccessors { |
| 390 FastElementsAccessor fast_elements_handler; | 504 FastElementsAccessor fast_elements_handler; |
| 391 FastDoubleElementsAccessor fast_double_elements_handler; | 505 FastDoubleElementsAccessor fast_double_elements_handler; |
| 392 DictionaryElementsAccessor dictionary_elements_handler; | 506 DictionaryElementsAccessor dictionary_elements_handler; |
| 393 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; | 507 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; |
| 394 ExternalByteElementsAccessor byte_elements_handler; | 508 ExternalByteElementsAccessor byte_elements_handler; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 416 &element_accessors.float_elements_handler, | 530 &element_accessors.float_elements_handler, |
| 417 &element_accessors.double_elements_handler, | 531 &element_accessors.double_elements_handler, |
| 418 &element_accessors.pixel_elements_handler | 532 &element_accessors.pixel_elements_handler |
| 419 }; | 533 }; |
| 420 | 534 |
| 421 elements_accessors_ = accessor_array; | 535 elements_accessors_ = accessor_array; |
| 422 } | 536 } |
| 423 | 537 |
| 424 | 538 |
| 425 } } // namespace v8::internal | 539 } } // namespace v8::internal |
| OLD | NEW |