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 |