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()); | |
144 result->set(len0 + index, value); | 142 result->set(len0 + index, value); |
145 index++; | 143 index++; |
146 } | 144 } |
147 } | 145 } |
148 ASSERT(extra == index); | 146 ASSERT(extra == index); |
149 return result; | 147 return result; |
150 } | 148 } |
151 | 149 |
152 static uint32_t GetCapacity(JSObject* obj) { | 150 static uint32_t GetLength(BackingStoreClass* backing_store) { |
153 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); | 151 return backing_store->length(); |
154 } | 152 } |
155 | 153 |
156 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 154 static uint32_t GetCapacity(BackingStoreClass* backing_store) { |
157 BackingStoreClass* backing_store = | 155 return GetLength(backing_store); |
158 ElementsAccessorSubclass::GetBackingStore(obj); | 156 } |
| 157 |
| 158 static MaybeObject* GetElementAtCapacityIndex( |
| 159 BackingStoreClass* backing_store, |
| 160 int index) { |
159 return backing_store->get(index); | 161 return backing_store->get(index); |
160 } | 162 } |
161 | 163 |
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: | 164 private: |
172 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 165 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
173 }; | 166 }; |
174 | 167 |
175 | 168 |
176 class FastElementsAccessor | 169 class FastElementsAccessor |
177 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { | 170 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { |
178 public: | 171 public: |
179 static MaybeObject* DeleteCommon(JSObject* obj, | 172 static MaybeObject* DeleteCommon(JSObject* obj, |
180 uint32_t index) { | 173 uint32_t index) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 // Super class for all external element arrays. | 241 // Super class for all external element arrays. |
249 template<typename ExternalElementsAccessorSubclass, | 242 template<typename ExternalElementsAccessorSubclass, |
250 typename ExternalArray> | 243 typename ExternalArray> |
251 class ExternalElementsAccessor | 244 class ExternalElementsAccessor |
252 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 245 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
253 ExternalArray> { | 246 ExternalArray> { |
254 public: | 247 public: |
255 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 248 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
256 Object* receiver, | 249 Object* receiver, |
257 uint32_t index) { | 250 uint32_t index) { |
258 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) { | 251 ExternalArray* backing_store = ExternalArray::cast(obj->elements()); |
259 ExternalArray* backing_store = | 252 if (index < ExternalElementsAccessorSubclass::GetLength(backing_store)) { |
260 ExternalElementsAccessorSubclass::GetBackingStore(obj); | |
261 return backing_store->get(index); | 253 return backing_store->get(index); |
262 } else { | 254 } else { |
263 return obj->GetHeap()->undefined_value(); | 255 return obj->GetHeap()->undefined_value(); |
264 } | 256 } |
265 } | 257 } |
266 | 258 |
267 virtual MaybeObject* Delete(JSObject* obj, | 259 virtual MaybeObject* Delete(JSObject* obj, |
268 uint32_t index, | 260 uint32_t index, |
269 JSReceiver::DeleteMode mode) { | 261 JSReceiver::DeleteMode mode) { |
270 // External arrays always ignore deletes. | 262 // External arrays always ignore deletes. |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 | 397 |
406 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 398 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
407 Object* receiver, | 399 Object* receiver, |
408 uint32_t index) { | 400 uint32_t index) { |
409 return GetNumberDictionaryElement(obj, | 401 return GetNumberDictionaryElement(obj, |
410 receiver, | 402 receiver, |
411 obj->element_dictionary(), | 403 obj->element_dictionary(), |
412 index); | 404 index); |
413 } | 405 } |
414 | 406 |
415 static uint32_t GetCapacity(JSObject* obj) { | 407 static uint32_t GetCapacity(NumberDictionary* dict) { |
416 return obj->element_dictionary()->Capacity(); | 408 return dict->Capacity(); |
417 } | 409 } |
418 | 410 |
419 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 411 static MaybeObject* GetElementAtCapacityIndex(NumberDictionary* dict, |
420 NumberDictionary* dict = obj->element_dictionary(); | 412 int index) { |
421 if (dict->IsKey(dict->KeyAt(index))) { | 413 if (dict->IsKey(dict->KeyAt(index))) { |
422 return dict->ValueAt(index); | 414 return dict->ValueAt(index); |
423 } else { | 415 } else { |
424 return obj->GetHeap()->the_hole_value(); | 416 return dict->GetHeap()->the_hole_value(); |
425 } | 417 } |
426 } | 418 } |
427 }; | 419 }; |
428 | 420 |
429 | 421 |
430 class NonStrictArgumentsElementsAccessor | 422 class NonStrictArgumentsElementsAccessor |
431 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 423 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
432 FixedArray> { | 424 FixedArray> { |
433 public: | 425 public: |
434 virtual MaybeObject* GetWithReceiver(JSObject* obj, | 426 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
435 Object* receiver, | 427 Object* receiver, |
436 uint32_t index) { | 428 uint32_t index) { |
437 FixedArray* parameter_map = GetBackingStore(obj); | 429 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
438 uint32_t length = parameter_map->length(); | 430 uint32_t length = parameter_map->length(); |
439 Object* probe = | 431 Object* probe = |
440 (index < length - 2) ? parameter_map->get(index + 2) : NULL; | 432 (index < length - 2) ? parameter_map->get(index + 2) : NULL; |
441 if (probe != NULL && !probe->IsTheHole()) { | 433 if (probe != NULL && !probe->IsTheHole()) { |
442 Context* context = Context::cast(parameter_map->get(0)); | 434 Context* context = Context::cast(parameter_map->get(0)); |
443 int context_index = Smi::cast(probe)->value(); | 435 int context_index = Smi::cast(probe)->value(); |
444 ASSERT(!context->get(context_index)->IsTheHole()); | 436 ASSERT(!context->get(context_index)->IsTheHole()); |
445 return context->get(context_index); | 437 return context->get(context_index); |
446 } else { | 438 } else { |
447 // Object is not mapped, defer to the arguments. | 439 // Object is not mapped, defer to the arguments. |
(...skipping 27 matching lines...) Expand all Loading... |
475 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 467 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
476 if (arguments->IsDictionary()) { | 468 if (arguments->IsDictionary()) { |
477 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); | 469 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); |
478 } else { | 470 } else { |
479 return FastElementsAccessor::DeleteCommon(obj, index); | 471 return FastElementsAccessor::DeleteCommon(obj, index); |
480 } | 472 } |
481 } | 473 } |
482 return obj->GetHeap()->true_value(); | 474 return obj->GetHeap()->true_value(); |
483 } | 475 } |
484 | 476 |
485 static uint32_t GetCapacity(JSObject* obj) { | 477 static uint32_t GetCapacity(FixedArray* obj) { |
486 // TODO(danno): Return max of parameter map length or backing store | 478 // TODO(danno): Return max of parameter map length or backing store |
487 // capacity. | 479 // capacity. |
488 return 0; | 480 return 0; |
489 } | 481 } |
490 | 482 |
491 static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) { | 483 static MaybeObject* GetElementAtCapacityIndex(FixedArray* obj, int index) { |
492 // TODO(danno): Return either value from parameter map of backing | 484 // TODO(danno): Return either value from parameter map of backing |
493 // store value at index. | 485 // store value at index. |
494 return obj->GetHeap()->the_hole_value(); | 486 return obj->GetHeap()->the_hole_value(); |
495 } | 487 } |
496 }; | 488 }; |
497 | 489 |
498 | 490 |
499 void ElementsAccessor::InitializeOncePerProcess() { | 491 void ElementsAccessor::InitializeOncePerProcess() { |
500 static struct ConcreteElementsAccessors { | 492 static struct ConcreteElementsAccessors { |
501 FastElementsAccessor fast_elements_handler; | 493 FastElementsAccessor fast_elements_handler; |
(...skipping 25 matching lines...) Expand all Loading... |
527 &element_accessors.float_elements_handler, | 519 &element_accessors.float_elements_handler, |
528 &element_accessors.double_elements_handler, | 520 &element_accessors.double_elements_handler, |
529 &element_accessors.pixel_elements_handler | 521 &element_accessors.pixel_elements_handler |
530 }; | 522 }; |
531 | 523 |
532 elements_accessors_ = accessor_array; | 524 elements_accessors_ = accessor_array; |
533 } | 525 } |
534 | 526 |
535 | 527 |
536 } } // namespace v8::internal | 528 } } // namespace v8::internal |
OLD | NEW |