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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use | 68 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
| 69 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and | 69 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
| 70 // specialization of SomeElementsAccessor methods). | 70 // specialization of SomeElementsAccessor methods). |
| 71 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | 71 template <typename ElementsAccessorSubclass, typename BackingStoreClass> |
| 72 class ElementsAccessorBase : public ElementsAccessor { | 72 class ElementsAccessorBase : public ElementsAccessor { |
| 73 public: | 73 public: |
| 74 ElementsAccessorBase() { } | 74 ElementsAccessorBase() { } |
| 75 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 75 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 76 Object* receiver, | 76 Object* receiver, |
| 77 uint32_t index) { | 77 uint32_t index) { |
| 78 if (index < ElementsAccessorSubclass::GetLength(obj)) { | 78 BackingStoreClass* backing_store = BackingStoreClass::cast(obj->elements()); |
| 79 BackingStoreClass* backing_store = | 79 if (index < ElementsAccessorSubclass::GetLength(backing_store)) { |
| 80 ElementsAccessorSubclass::GetBackingStore(obj); | |
| 81 return backing_store->get(index); | 80 return backing_store->get(index); |
| 82 } | 81 } |
| 83 return obj->GetHeap()->the_hole_value(); | 82 return obj->GetHeap()->the_hole_value(); |
| 84 } | 83 } |
| 85 | 84 |
| 86 virtual MaybeObject* Delete(JSObject* obj, | 85 virtual MaybeObject* Delete(JSObject* obj, |
| 87 uint32_t index, | 86 uint32_t index, |
| 88 JSReceiver::DeleteMode mode) = 0; | 87 JSReceiver::DeleteMode mode) = 0; |
| 89 | 88 |
| 90 virtual MaybeObject* AddJSArrayKeysToFixedArray(JSArray* other, | 89 virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from, |
| 91 FixedArray* keys) { | 90 FixedArray* to) { |
| 92 int len0 = keys->length(); | 91 int len0 = to->length(); |
| 93 #ifdef DEBUG | 92 #ifdef DEBUG |
| 94 if (FLAG_enable_slow_asserts) { | 93 if (FLAG_enable_slow_asserts) { |
| 95 for (int i = 0; i < len0; i++) { | 94 for (int i = 0; i < len0; i++) { |
| 96 ASSERT(keys->get(i)->IsString() || keys->get(i)->IsNumber()); | 95 ASSERT(!to->get(i)->IsTheHole()); |
| 97 } | 96 } |
| 98 } | 97 } |
| 99 #endif | 98 #endif |
| 100 int len1 = ElementsAccessorSubclass::GetCapacity(other); | 99 BackingStoreClass* backing_store = BackingStoreClass::cast(from); |
| 100 int len1 = ElementsAccessorSubclass::GetCapacity(backing_store); | |
| 101 | 101 |
| 102 // Optimize if 'other' is empty. | 102 // Optimize if 'other' is empty. |
| 103 // We cannot optimize if 'this' is empty, as other may have holes | 103 // We cannot optimize if 'this' is empty, as other may have holes. |
| 104 // or non keys. | 104 if (len1 == 0) return to; |
| 105 if (len1 == 0) return keys; | |
| 106 | 105 |
| 107 // Compute how many elements are not in other. | 106 // Compute how many elements are not in other. |
| 108 int extra = 0; | 107 int extra = 0; |
| 109 for (int y = 0; y < len1; y++) { | 108 for (int y = 0; y < len1; y++) { |
| 110 Object* value; | 109 Object* value; |
| 111 MaybeObject* maybe_value = | 110 MaybeObject* maybe_value = |
| 112 ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y); | 111 ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y); |
| 113 if (!maybe_value->ToObject(&value)) return maybe_value; | 112 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 114 if (!value->IsTheHole() && !HasKey(keys, value)) extra++; | 113 if (!value->IsTheHole() && !HasKey(to, value)) extra++; |
| 115 } | 114 } |
| 116 | 115 |
| 117 if (extra == 0) return keys; | 116 if (extra == 0) return to; |
| 118 | 117 |
| 119 // Allocate the result | 118 // Allocate the result |
| 120 FixedArray* result; | 119 FixedArray* result; |
| 121 MaybeObject* maybe_obj = | 120 MaybeObject* maybe_obj = |
| 122 other->GetHeap()->AllocateFixedArray(len0 + extra); | 121 backing_store->GetHeap()->AllocateFixedArray(len0 + extra); |
| 123 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; | 122 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; |
| 124 | 123 |
| 125 // Fill in the content | 124 // Fill in the content |
| 126 { | 125 { |
| 127 AssertNoAllocation no_gc; | 126 AssertNoAllocation no_gc; |
| 128 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 127 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 129 for (int i = 0; i < len0; i++) { | 128 for (int i = 0; i < len0; i++) { |
| 130 Object* e = keys->get(i); | 129 Object* e = to->get(i); |
| 131 ASSERT(e->IsString() || e->IsNumber()); | 130 ASSERT(e->IsString() || e->IsNumber()); |
| 132 result->set(i, e, mode); | 131 result->set(i, e, mode); |
| 133 } | 132 } |
| 134 } | 133 } |
| 135 // Fill in the extra keys. | 134 // Fill in the extra values. |
| 136 int index = 0; | 135 int index = 0; |
| 137 for (int y = 0; y < len1; y++) { | 136 for (int y = 0; y < len1; y++) { |
| 138 MaybeObject* maybe_value = | 137 MaybeObject* maybe_value = |
| 139 ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y); | 138 ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y); |
| 140 Object* value; | 139 Object* value; |
| 141 if (!maybe_value->ToObject(&value)) return maybe_value; | 140 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 142 if (!value->IsTheHole() && !HasKey(keys, value)) { | 141 if (!value->IsTheHole() && !HasKey(to, value)) { |
| 143 ASSERT(value->IsString() || value->IsNumber()); | 142 ASSERT(value->IsString() || value->IsNumber()); |
|
Sven Panne
2011/08/12 08:20:43
This ASSERT should be removed to make this method
| |
| 144 result->set(len0 + index, value); | 143 result->set(len0 + index, value); |
| 145 index++; | 144 index++; |
| 146 } | 145 } |
| 147 } | 146 } |
| 148 ASSERT(extra == index); | 147 ASSERT(extra == index); |
| 149 return result; | 148 return result; |
| 150 } | 149 } |
| 151 | 150 |
| 152 static uint32_t GetCapacity(JSObject* obj) { | 151 static uint32_t GetLength(BackingStoreClass* backing_store) { |
| 153 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | 152 return backing_store->length(); |
| 154 } | 153 } |
| 155 | 154 |
| 156 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 155 static uint32_t GetCapacity(BackingStoreClass* backing_store) { |
| 157 BackingStoreClass* backing_store = | 156 return GetLength(backing_store); |
| 158 ElementsAccessorSubclass::GetBackingStore(obj); | 157 } |
| 158 | |
| 159 static MaybeObject* GetElementAtCapacityIndex( | |
| 160 BackingStoreClass* backing_store, | |
| 161 int index) { | |
| 159 return backing_store->get(index); | 162 return backing_store->get(index); |
| 160 } | 163 } |
| 161 | 164 |
| 162 protected: | |
| 163 static BackingStoreClass* GetBackingStore(JSObject* obj) { | |
| 164 return BackingStoreClass::cast(obj->elements()); | |
| 165 } | |
| 166 | |
| 167 static uint32_t GetLength(JSObject* obj) { | |
| 168 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | |
| 169 } | |
| 170 | |
| 171 private: | 165 private: |
| 172 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 166 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 173 }; | 167 }; |
| 174 | 168 |
| 175 | 169 |
| 176 class FastElementsAccessor | 170 class FastElementsAccessor |
| 177 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { | 171 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { |
| 178 public: | 172 public: |
| 179 static MaybeObject* DeleteCommon(JSObject* obj, | 173 static MaybeObject* DeleteCommon(JSObject* obj, |
| 180 uint32_t index) { | 174 uint32_t index) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 // Super class for all external element arrays. | 242 // Super class for all external element arrays. |
| 249 template<typename ExternalElementsAccessorSubclass, | 243 template<typename ExternalElementsAccessorSubclass, |
| 250 typename ExternalArray> | 244 typename ExternalArray> |
| 251 class ExternalElementsAccessor | 245 class ExternalElementsAccessor |
| 252 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 246 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 253 ExternalArray> { | 247 ExternalArray> { |
| 254 public: | 248 public: |
| 255 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 249 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 256 Object* receiver, | 250 Object* receiver, |
| 257 uint32_t index) { | 251 uint32_t index) { |
| 258 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) { | 252 ExternalArray* backing_store = ExternalArray::cast(obj->elements()); |
| 259 ExternalArray* backing_store = | 253 if (index < ExternalElementsAccessorSubclass::GetLength(backing_store)) { |
| 260 ExternalElementsAccessorSubclass::GetBackingStore(obj); | |
| 261 return backing_store->get(index); | 254 return backing_store->get(index); |
| 262 } else { | 255 } else { |
| 263 return obj->GetHeap()->undefined_value(); | 256 return obj->GetHeap()->undefined_value(); |
| 264 } | 257 } |
| 265 } | 258 } |
| 266 | 259 |
| 267 virtual MaybeObject* Delete(JSObject* obj, | 260 virtual MaybeObject* Delete(JSObject* obj, |
| 268 uint32_t index, | 261 uint32_t index, |
| 269 JSReceiver::DeleteMode mode) { | 262 JSReceiver::DeleteMode mode) { |
| 270 // External arrays always ignore deletes. | 263 // External arrays always ignore deletes. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 | 398 |
| 406 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 399 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 407 Object* receiver, | 400 Object* receiver, |
| 408 uint32_t index) { | 401 uint32_t index) { |
| 409 return GetNumberDictionaryElement(obj, | 402 return GetNumberDictionaryElement(obj, |
| 410 receiver, | 403 receiver, |
| 411 obj->element_dictionary(), | 404 obj->element_dictionary(), |
| 412 index); | 405 index); |
| 413 } | 406 } |
| 414 | 407 |
| 415 static uint32_t GetCapacity(JSObject* obj) { | 408 static uint32_t GetCapacity(NumberDictionary* dict) { |
| 416 return obj->element_dictionary()->Capacity(); | 409 return dict->Capacity(); |
| 417 } | 410 } |
| 418 | 411 |
| 419 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 412 static MaybeObject* GetElementAtCapacityIndex(NumberDictionary* dict, |
| 420 NumberDictionary* dict = obj->element_dictionary(); | 413 int index) { |
| 421 if (dict->IsKey(dict->KeyAt(index))) { | 414 if (dict->IsKey(dict->KeyAt(index))) { |
| 422 return dict->ValueAt(index); | 415 return dict->ValueAt(index); |
| 423 } else { | 416 } else { |
| 424 return obj->GetHeap()->the_hole_value(); | 417 return dict->GetHeap()->the_hole_value(); |
| 425 } | 418 } |
| 426 } | 419 } |
| 427 }; | 420 }; |
| 428 | 421 |
| 429 | 422 |
| 430 class NonStrictArgumentsElementsAccessor | 423 class NonStrictArgumentsElementsAccessor |
| 431 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 424 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 432 FixedArray> { | 425 FixedArray> { |
| 433 public: | 426 public: |
| 434 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 427 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 435 Object* receiver, | 428 Object* receiver, |
| 436 uint32_t index) { | 429 uint32_t index) { |
| 437 FixedArray* parameter_map = GetBackingStore(obj); | 430 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| 438 uint32_t length = parameter_map->length(); | 431 uint32_t length = parameter_map->length(); |
| 439 Object* probe = | 432 Object* probe = |
| 440 (index < length - 2) ? parameter_map->get(index + 2) : NULL; | 433 (index < length - 2) ? parameter_map->get(index + 2) : NULL; |
| 441 if (probe != NULL && !probe->IsTheHole()) { | 434 if (probe != NULL && !probe->IsTheHole()) { |
| 442 Context* context = Context::cast(parameter_map->get(0)); | 435 Context* context = Context::cast(parameter_map->get(0)); |
| 443 int context_index = Smi::cast(probe)->value(); | 436 int context_index = Smi::cast(probe)->value(); |
| 444 ASSERT(!context->get(context_index)->IsTheHole()); | 437 ASSERT(!context->get(context_index)->IsTheHole()); |
| 445 return context->get(context_index); | 438 return context->get(context_index); |
| 446 } else { | 439 } else { |
| 447 // Object is not mapped, defer to the arguments. | 440 // Object is not mapped, defer to the arguments. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 475 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 468 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 476 if (arguments->IsDictionary()) { | 469 if (arguments->IsDictionary()) { |
| 477 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); | 470 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); |
| 478 } else { | 471 } else { |
| 479 return FastElementsAccessor::DeleteCommon(obj, index); | 472 return FastElementsAccessor::DeleteCommon(obj, index); |
| 480 } | 473 } |
| 481 } | 474 } |
| 482 return obj->GetHeap()->true_value(); | 475 return obj->GetHeap()->true_value(); |
| 483 } | 476 } |
| 484 | 477 |
| 485 static uint32_t GetCapacity(JSObject* obj) { | 478 static uint32_t GetCapacity(FixedArray* obj) { |
| 486 // TODO(danno): Return max of parameter map length or backing store | 479 // TODO(danno): Return max of parameter map length or backing store |
| 487 // capacity. | 480 // capacity. |
| 488 return 0; | 481 return 0; |
| 489 } | 482 } |
| 490 | 483 |
| 491 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 484 static MaybeObject* GetElementAtCapacityIndex(FixedArray* obj, int index) { |
| 492 // TODO(danno): Return either value from parameter map of backing | 485 // TODO(danno): Return either value from parameter map of backing |
| 493 // store value at index. | 486 // store value at index. |
| 494 return obj->GetHeap()->the_hole_value(); | 487 return obj->GetHeap()->the_hole_value(); |
| 495 } | 488 } |
| 496 }; | 489 }; |
| 497 | 490 |
| 498 | 491 |
| 499 void ElementsAccessor::InitializeOncePerProcess() { | 492 void ElementsAccessor::InitializeOncePerProcess() { |
| 500 static struct ConcreteElementsAccessors { | 493 static struct ConcreteElementsAccessors { |
| 501 FastElementsAccessor fast_elements_handler; | 494 FastElementsAccessor fast_elements_handler; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 527 &element_accessors.float_elements_handler, | 520 &element_accessors.float_elements_handler, |
| 528 &element_accessors.double_elements_handler, | 521 &element_accessors.double_elements_handler, |
| 529 &element_accessors.pixel_elements_handler | 522 &element_accessors.pixel_elements_handler |
| 530 }; | 523 }; |
| 531 | 524 |
| 532 elements_accessors_ = accessor_array; | 525 elements_accessors_ = accessor_array; |
| 533 } | 526 } |
| 534 | 527 |
| 535 | 528 |
| 536 } } // namespace v8::internal | 529 } } // namespace v8::internal |
| OLD | NEW |