OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 // - ExternalDoubleElementsAccessor | 52 // - ExternalDoubleElementsAccessor |
53 // - PixelElementsAccessor | 53 // - PixelElementsAccessor |
54 // - DictionaryElementsAccessor | 54 // - DictionaryElementsAccessor |
55 // - NonStrictArgumentsElementsAccessor | 55 // - NonStrictArgumentsElementsAccessor |
56 | 56 |
57 | 57 |
58 namespace v8 { | 58 namespace v8 { |
59 namespace internal { | 59 namespace internal { |
60 | 60 |
61 | 61 |
62 // First argument in list is the accessor class, the second argument is the | |
63 // accessor ElementsKind, and the third is the backing store class. Use the | |
64 // fast element handler for smi-only arrays. The implementation is currently | |
65 // identical. Note that the order must match that of the ElementsKind enum for | |
Jakob Kummerow
2012/03/09 10:09:36
It sure would be nice to enforce this matching ord
danno
2012/03/09 12:12:35
I think it would be nice, but it's a bit beyond th
| |
66 // the |accessor_array[]| below to work. | |
67 #define ELEMENTS_LIST(V) \ | |
68 V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray) \ | |
69 V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ | |
70 V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \ | |
71 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ | |
72 SeededNumberDictionary) \ | |
73 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \ | |
74 FixedArray) \ | |
75 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \ | |
76 ExternalByteArray) \ | |
77 V(ExternalUnsignedByteElementsAccessor, \ | |
78 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \ | |
79 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \ | |
80 ExternalShortArray) \ | |
81 V(ExternalUnsignedShortElementsAccessor, \ | |
82 EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \ | |
83 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \ | |
84 ExternalIntArray) \ | |
85 V(ExternalUnsignedIntElementsAccessor, \ | |
86 EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \ | |
87 V(ExternalFloatElementsAccessor, \ | |
88 EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \ | |
89 V(ExternalDoubleElementsAccessor, \ | |
90 EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \ | |
91 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray) | |
92 | |
93 | |
94 template<ElementsKind Kind> class ElementsKindTraits { | |
95 public: | |
96 typedef FixedArray BackingStore; | |
97 }; | |
98 | |
99 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ | |
100 template<> class ElementsKindTraits<KindParam> { \ | |
101 public: \ | |
102 static const ElementsKind Kind = KindParam; \ | |
103 typedef Store BackingStore; \ | |
104 }; | |
105 ELEMENTS_LIST(ELEMENTS_TRAITS) | |
106 #undef ELEMENTS_TRAITS | |
107 | |
108 | |
62 ElementsAccessor** ElementsAccessor::elements_accessors_; | 109 ElementsAccessor** ElementsAccessor::elements_accessors_; |
63 | 110 |
64 | 111 |
65 static bool HasKey(FixedArray* array, Object* key) { | 112 static bool HasKey(FixedArray* array, Object* key) { |
66 int len0 = array->length(); | 113 int len0 = array->length(); |
67 for (int i = 0; i < len0; i++) { | 114 for (int i = 0; i < len0; i++) { |
68 Object* element = array->get(i); | 115 Object* element = array->get(i); |
69 if (element->IsSmi() && element == key) return true; | 116 if (element->IsSmi() && element == key) return true; |
70 if (element->IsString() && | 117 if (element->IsString() && |
71 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 118 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
72 return true; | 119 return true; |
73 } | 120 } |
74 } | 121 } |
75 return false; | 122 return false; |
76 } | 123 } |
77 | 124 |
78 | 125 |
79 static Failure* ThrowArrayLengthRangeError(Heap* heap) { | 126 static Failure* ThrowArrayLengthRangeError(Heap* heap) { |
80 HandleScope scope(heap->isolate()); | 127 HandleScope scope(heap->isolate()); |
81 return heap->isolate()->Throw( | 128 return heap->isolate()->Throw( |
82 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | 129 *heap->isolate()->factory()->NewRangeError("invalid_array_length", |
83 HandleVector<Object>(NULL, 0))); | 130 HandleVector<Object>(NULL, 0))); |
84 } | 131 } |
85 | 132 |
86 | 133 |
134 void CopyObjectToObjectElements(AssertNoAllocation* no_gc, | |
135 FixedArray* from_obj, | |
136 ElementsKind from_kind, | |
137 uint32_t from_start, | |
138 FixedArray* to_obj, | |
139 ElementsKind to_kind, | |
140 uint32_t to_start, | |
141 int copy_size) { | |
142 ASSERT(to_obj->map() != HEAP->fixed_cow_array_map()); | |
143 ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS); | |
144 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); | |
145 ASSERT(copy_size == -1 || | |
146 ((copy_size + static_cast<int>(to_start)) <= to_obj->length() && | |
147 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); | |
148 if (copy_size == -1) copy_size = from_obj->length() - from_start; | |
Jakob Kummerow
2012/03/09 10:09:36
I'd move this line up so that the auto-detected co
danno
2012/03/09 12:12:35
Done.
| |
149 if (copy_size == 0) return; | |
150 Address to = to_obj->address() + FixedArray::kHeaderSize; | |
151 Address from = from_obj->address() + FixedArray::kHeaderSize; | |
152 CopyWords(reinterpret_cast<Object**>(to) + to_start, | |
153 reinterpret_cast<Object**>(from) + from_start, | |
154 copy_size); | |
155 if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) { | |
156 Heap* heap = from_obj->GetHeap(); | |
157 WriteBarrierMode mode = to_obj->GetWriteBarrierMode(*no_gc); | |
158 if (mode == UPDATE_WRITE_BARRIER) { | |
159 heap->RecordWrites(to_obj->address(), | |
160 to_obj->OffsetOfElementAt(to_start), | |
161 copy_size); | |
162 } | |
163 heap->incremental_marking()->RecordWrites(to_obj); | |
164 } | |
165 } | |
166 | |
167 | |
168 | |
169 | |
170 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, | |
171 uint32_t from_start, | |
172 FixedArray* to, | |
173 ElementsKind to_kind, | |
174 uint32_t to_start, | |
175 int copy_size) { | |
176 ASSERT(to != from); | |
177 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); | |
178 ASSERT(copy_size == -1 || | |
179 (copy_size + static_cast<int>(to_start)) <= to->length()); | |
180 WriteBarrierMode mode = to_kind == FAST_ELEMENTS | |
181 ? UPDATE_WRITE_BARRIER | |
182 : SKIP_WRITE_BARRIER; | |
183 for (int i = 0; i < from->Capacity(); ++i) { | |
184 Object* key = from->KeyAt(i); | |
185 if (key->IsNumber()) { | |
186 uint32_t entry = static_cast<uint32_t>(key->Number()); | |
187 if ((entry >= to_start) && | |
188 (entry < to_start + copy_size || copy_size == -1)) { | |
189 Object* value = from->ValueAt(i); | |
190 ASSERT(to_kind == FAST_ELEMENTS || value->IsSmi()); | |
191 to->set(entry, value, mode); | |
192 } | |
193 } | |
194 } | |
195 } | |
196 | |
197 | |
198 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( | |
199 FixedDoubleArray* from_obj, | |
200 uint32_t from_start, | |
201 FixedArray* to_obj, | |
202 ElementsKind to_kind, | |
203 uint32_t to_start, | |
204 int copy_size) { | |
205 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); | |
206 ASSERT(copy_size == -1 || | |
207 ((copy_size + static_cast<int>(to_start)) <= to_obj->length() && | |
208 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); | |
209 if (copy_size == -1) copy_size = from_obj->length() - from_start; | |
Jakob Kummerow
2012/03/09 10:09:36
I'd move this up too (see my other comment above).
danno
2012/03/09 12:12:35
Done.
| |
210 if (copy_size == 0) return from_obj; | |
211 for (int i = 0; i < copy_size; ++i) { | |
212 if (to_kind == FAST_SMI_ONLY_ELEMENTS) { | |
213 UNIMPLEMENTED(); | |
214 return Failure::Exception(); | |
215 } else { | |
216 MaybeObject* maybe_value = from_obj->get(i + from_start); | |
217 Object* value; | |
218 ASSERT(to_kind == FAST_ELEMENTS); | |
219 // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects | |
220 // iteratively, the allocate must succeed within a single GC cycle, | |
221 // otherwise the retry after the GC will also fail. In order to ensure | |
222 // that no GC is triggered, allocate HeapNumbers from old space if they | |
223 // can't be taken from new space. | |
224 if (!maybe_value->ToObject(&value)) { | |
225 Heap* heap = from_obj->GetHeap(); | |
226 MaybeObject* maybe_value_object = | |
227 heap->AllocateHeapNumber(from_obj->get_scalar(i), TENURED); | |
228 CHECK(maybe_value_object->ToObject(&value)); | |
Jakob Kummerow
2012/03/09 10:09:36
What if the old space needs a GC? I think you want
danno
2012/03/09 12:12:35
Done.
| |
229 } | |
230 to_obj->set(i + to_start, value, UPDATE_WRITE_BARRIER); | |
231 } | |
232 } | |
233 return to_obj; | |
234 } | |
235 | |
236 | |
237 static void CopyDoubleToDoubleElements(FixedDoubleArray* from_obj, | |
238 uint32_t from_start, | |
239 FixedDoubleArray* to_obj, | |
240 uint32_t to_start, | |
241 int copy_size) { | |
242 ASSERT(copy_size == -1 || | |
243 ((copy_size + static_cast<int>(to_start)) <= to_obj->length() && | |
244 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); | |
245 if (copy_size == -1) copy_size = from_obj->length() - from_start; | |
Jakob Kummerow
2012/03/09 10:09:36
And once more, I'd move this up.
danno
2012/03/09 12:12:35
Done.
| |
246 if (copy_size == 0) return; | |
247 Address to = to_obj->address() + FixedDoubleArray::kHeaderSize; | |
248 Address from = from_obj->address() + FixedDoubleArray::kHeaderSize; | |
249 to += kDoubleSize * to_start; | |
250 from += kDoubleSize * from_start; | |
251 int words_per_double = (kDoubleSize / kPointerSize); | |
252 CopyWords(reinterpret_cast<Object**>(to), | |
253 reinterpret_cast<Object**>(from), | |
254 words_per_double * copy_size); | |
255 } | |
256 | |
257 | |
87 // Base class for element handler implementations. Contains the | 258 // Base class for element handler implementations. Contains the |
88 // the common logic for objects with different ElementsKinds. | 259 // the common logic for objects with different ElementsKinds. |
89 // Subclasses must specialize method for which the element | 260 // Subclasses must specialize method for which the element |
90 // implementation differs from the base class implementation. | 261 // implementation differs from the base class implementation. |
91 // | 262 // |
92 // This class is intended to be used in the following way: | 263 // This class is intended to be used in the following way: |
93 // | 264 // |
94 // class SomeElementsAccessor : | 265 // class SomeElementsAccessor : |
95 // public ElementsAccessorBase<SomeElementsAccessor, | 266 // public ElementsAccessorBase<SomeElementsAccessor, |
96 // BackingStoreClass> { | 267 // BackingStoreClass> { |
97 // ... | 268 // ... |
98 // } | 269 // } |
99 // | 270 // |
100 // This is an example of the Curiously Recurring Template Pattern (see | 271 // This is an example of the Curiously Recurring Template Pattern (see |
101 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use | 272 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
102 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and | 273 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
103 // specialization of SomeElementsAccessor methods). | 274 // specialization of SomeElementsAccessor methods). |
104 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | 275 template <typename ElementsAccessorSubclass, |
276 typename ElementsTraitsParam> | |
105 class ElementsAccessorBase : public ElementsAccessor { | 277 class ElementsAccessorBase : public ElementsAccessor { |
106 protected: | 278 protected: |
107 explicit ElementsAccessorBase(const char* name) : ElementsAccessor(name) { } | 279 explicit ElementsAccessorBase(const char* name) |
280 : ElementsAccessor(name) { } | |
281 | |
282 typedef ElementsTraitsParam ElementsTraits; | |
283 typedef typename ElementsTraitsParam::BackingStore BackingStore; | |
284 | |
285 virtual ElementsKind kind() const { return ElementsTraits::Kind; } | |
108 | 286 |
109 static bool HasElementImpl(Object* receiver, | 287 static bool HasElementImpl(Object* receiver, |
110 JSObject* holder, | 288 JSObject* holder, |
111 uint32_t key, | 289 uint32_t key, |
112 BackingStoreClass* backing_store) { | 290 BackingStore* backing_store) { |
113 MaybeObject* element = | 291 MaybeObject* element = |
114 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); | 292 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); |
115 return !element->IsTheHole(); | 293 return !element->IsTheHole(); |
116 } | 294 } |
117 | 295 |
118 virtual bool HasElement(Object* receiver, | 296 virtual bool HasElement(Object* receiver, |
119 JSObject* holder, | 297 JSObject* holder, |
120 uint32_t key, | 298 uint32_t key, |
121 FixedArrayBase* backing_store) { | 299 FixedArrayBase* backing_store) { |
122 if (backing_store == NULL) { | 300 if (backing_store == NULL) { |
123 backing_store = holder->elements(); | 301 backing_store = holder->elements(); |
124 } | 302 } |
125 return ElementsAccessorSubclass::HasElementImpl( | 303 return ElementsAccessorSubclass::HasElementImpl( |
126 receiver, holder, key, BackingStoreClass::cast(backing_store)); | 304 receiver, holder, key, BackingStore::cast(backing_store)); |
127 } | 305 } |
128 | 306 |
129 virtual MaybeObject* Get(Object* receiver, | 307 virtual MaybeObject* Get(Object* receiver, |
130 JSObject* holder, | 308 JSObject* holder, |
131 uint32_t key, | 309 uint32_t key, |
132 FixedArrayBase* backing_store) { | 310 FixedArrayBase* backing_store) { |
133 if (backing_store == NULL) { | 311 if (backing_store == NULL) { |
134 backing_store = holder->elements(); | 312 backing_store = holder->elements(); |
135 } | 313 } |
136 return ElementsAccessorSubclass::GetImpl( | 314 return ElementsAccessorSubclass::GetImpl( |
137 receiver, holder, key, BackingStoreClass::cast(backing_store)); | 315 receiver, holder, key, BackingStore::cast(backing_store)); |
138 } | 316 } |
139 | 317 |
140 static MaybeObject* GetImpl(Object* receiver, | 318 static MaybeObject* GetImpl(Object* receiver, |
141 JSObject* obj, | 319 JSObject* obj, |
142 uint32_t key, | 320 uint32_t key, |
143 BackingStoreClass* backing_store) { | 321 BackingStore* backing_store) { |
144 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) | 322 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) |
145 ? backing_store->get(key) | 323 ? backing_store->get(key) |
146 : backing_store->GetHeap()->the_hole_value(); | 324 : backing_store->GetHeap()->the_hole_value(); |
147 } | 325 } |
148 | 326 |
149 virtual MaybeObject* SetLength(JSArray* array, | 327 virtual MaybeObject* SetLength(JSArray* array, |
150 Object* length) { | 328 Object* length) { |
151 return ElementsAccessorSubclass::SetLengthImpl( | 329 return ElementsAccessorSubclass::SetLengthImpl( |
152 array, length, BackingStoreClass::cast(array->elements())); | 330 array, length, BackingStore::cast(array->elements())); |
153 } | 331 } |
154 | 332 |
155 static MaybeObject* SetLengthImpl(JSObject* obj, | 333 static MaybeObject* SetLengthImpl(JSObject* obj, |
156 Object* length, | 334 Object* length, |
157 BackingStoreClass* backing_store); | 335 BackingStore* backing_store); |
158 | 336 |
159 virtual MaybeObject* SetCapacityAndLength(JSArray* array, | 337 virtual MaybeObject* SetCapacityAndLength(JSArray* array, |
160 int capacity, | 338 int capacity, |
161 int length) { | 339 int length) { |
162 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 340 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
163 array, | 341 array, |
164 capacity, | 342 capacity, |
165 length); | 343 length); |
166 } | 344 } |
167 | 345 |
168 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 346 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
169 int capacity, | 347 int capacity, |
170 int length) { | 348 int length) { |
171 UNIMPLEMENTED(); | 349 UNIMPLEMENTED(); |
172 return obj; | 350 return obj; |
173 } | 351 } |
174 | 352 |
175 virtual MaybeObject* Delete(JSObject* obj, | 353 virtual MaybeObject* Delete(JSObject* obj, |
176 uint32_t key, | 354 uint32_t key, |
177 JSReceiver::DeleteMode mode) = 0; | 355 JSReceiver::DeleteMode mode) = 0; |
178 | 356 |
357 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | |
358 uint32_t from_start, | |
359 FixedArrayBase* to, | |
360 ElementsKind to_kind, | |
361 uint32_t to_start, | |
362 int copy_size) { | |
363 UNREACHABLE(); | |
364 return NULL; | |
365 } | |
366 | |
367 virtual MaybeObject* CopyElements(JSObject* from_holder, | |
368 uint32_t from_start, | |
369 FixedArrayBase* to, | |
370 ElementsKind to_kind, | |
371 uint32_t to_start, | |
372 int copy_size, | |
373 FixedArrayBase* from) { | |
374 if (from == NULL) { | |
375 from = from_holder->elements(); | |
376 } | |
377 return ElementsAccessorSubclass::CopyElementsImpl( | |
378 from, from_start, to, to_kind, to_start, copy_size); | |
379 } | |
380 | |
179 virtual MaybeObject* AddElementsToFixedArray(Object* receiver, | 381 virtual MaybeObject* AddElementsToFixedArray(Object* receiver, |
180 JSObject* holder, | 382 JSObject* holder, |
181 FixedArray* to, | 383 FixedArray* to, |
182 FixedArrayBase* from) { | 384 FixedArrayBase* from) { |
183 int len0 = to->length(); | 385 int len0 = to->length(); |
184 #ifdef DEBUG | 386 #ifdef DEBUG |
185 if (FLAG_enable_slow_asserts) { | 387 if (FLAG_enable_slow_asserts) { |
186 for (int i = 0; i < len0; i++) { | 388 for (int i = 0; i < len0; i++) { |
187 ASSERT(!to->get(i)->IsTheHole()); | 389 ASSERT(!to->get(i)->IsTheHole()); |
188 } | 390 } |
189 } | 391 } |
190 #endif | 392 #endif |
191 if (from == NULL) { | 393 if (from == NULL) { |
192 from = holder->elements(); | 394 from = holder->elements(); |
193 } | 395 } |
194 BackingStoreClass* backing_store = BackingStoreClass::cast(from); | 396 BackingStore* backing_store = BackingStore::cast(from); |
195 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); | 397 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); |
196 | 398 |
197 // Optimize if 'other' is empty. | 399 // Optimize if 'other' is empty. |
198 // We cannot optimize if 'this' is empty, as other may have holes. | 400 // We cannot optimize if 'this' is empty, as other may have holes. |
199 if (len1 == 0) return to; | 401 if (len1 == 0) return to; |
200 | 402 |
201 // Compute how many elements are not in other. | 403 // Compute how many elements are not in other. |
202 uint32_t extra = 0; | 404 uint32_t extra = 0; |
203 for (uint32_t y = 0; y < len1; y++) { | 405 for (uint32_t y = 0; y < len1; y++) { |
204 uint32_t key = | 406 uint32_t key = |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 result->set(len0 + index, value); | 453 result->set(len0 + index, value); |
252 index++; | 454 index++; |
253 } | 455 } |
254 } | 456 } |
255 } | 457 } |
256 ASSERT(extra == index); | 458 ASSERT(extra == index); |
257 return result; | 459 return result; |
258 } | 460 } |
259 | 461 |
260 protected: | 462 protected: |
261 static uint32_t GetCapacityImpl(BackingStoreClass* backing_store) { | 463 static uint32_t GetCapacityImpl(BackingStore* backing_store) { |
262 return backing_store->length(); | 464 return backing_store->length(); |
263 } | 465 } |
264 | 466 |
265 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { | 467 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { |
266 return ElementsAccessorSubclass::GetCapacityImpl( | 468 return ElementsAccessorSubclass::GetCapacityImpl( |
267 BackingStoreClass::cast(backing_store)); | 469 BackingStore::cast(backing_store)); |
268 } | 470 } |
269 | 471 |
270 static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store, | 472 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store, |
271 uint32_t index) { | 473 uint32_t index) { |
272 return index; | 474 return index; |
273 } | 475 } |
274 | 476 |
275 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 477 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, |
276 uint32_t index) { | 478 uint32_t index) { |
277 return ElementsAccessorSubclass::GetKeyForIndexImpl( | 479 return ElementsAccessorSubclass::GetKeyForIndexImpl( |
278 BackingStoreClass::cast(backing_store), index); | 480 BackingStore::cast(backing_store), index); |
279 } | 481 } |
280 | 482 |
281 private: | 483 private: |
282 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 484 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
283 }; | 485 }; |
284 | 486 |
285 | 487 |
286 // Super class for all fast element arrays. | 488 // Super class for all fast element arrays. |
287 template<typename FastElementsAccessorSubclass, | 489 template<typename FastElementsAccessorSubclass, |
288 typename BackingStore, | 490 typename KindTraits, |
289 int ElementSize> | 491 int ElementSize> |
290 class FastElementsAccessor | 492 class FastElementsAccessor |
291 : public ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore> { | 493 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
292 public: | 494 public: |
293 explicit FastElementsAccessor(const char* name) | 495 explicit FastElementsAccessor(const char* name) |
294 : ElementsAccessorBase<FastElementsAccessorSubclass, | 496 : ElementsAccessorBase<FastElementsAccessorSubclass, |
295 BackingStore>(name) {} | 497 KindTraits>(name) {} |
296 protected: | 498 protected: |
297 friend class ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore>; | 499 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
500 | |
501 typedef typename KindTraits::BackingStore BackingStore; | |
298 | 502 |
299 // Adjusts the length of the fast backing store or returns the new length or | 503 // Adjusts the length of the fast backing store or returns the new length or |
300 // undefined in case conversion to a slow backing store should be performed. | 504 // undefined in case conversion to a slow backing store should be performed. |
301 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 505 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, |
302 JSArray* array, | 506 JSArray* array, |
303 Object* length_object, | 507 Object* length_object, |
304 uint32_t length) { | 508 uint32_t length) { |
305 uint32_t old_capacity = backing_store->length(); | 509 uint32_t old_capacity = backing_store->length(); |
306 | 510 |
307 // Check whether the backing store should be shrunk. | 511 // Check whether the backing store should be shrunk. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 } | 546 } |
343 | 547 |
344 // Request conversion to slow elements. | 548 // Request conversion to slow elements. |
345 return array->GetHeap()->undefined_value(); | 549 return array->GetHeap()->undefined_value(); |
346 } | 550 } |
347 }; | 551 }; |
348 | 552 |
349 | 553 |
350 class FastObjectElementsAccessor | 554 class FastObjectElementsAccessor |
351 : public FastElementsAccessor<FastObjectElementsAccessor, | 555 : public FastElementsAccessor<FastObjectElementsAccessor, |
352 FixedArray, | 556 ElementsKindTraits<FAST_ELEMENTS>, |
353 kPointerSize> { | 557 kPointerSize> { |
354 public: | 558 public: |
355 explicit FastObjectElementsAccessor(const char* name) | 559 explicit FastObjectElementsAccessor(const char* name) |
356 : FastElementsAccessor<FastObjectElementsAccessor, | 560 : FastElementsAccessor<FastObjectElementsAccessor, |
357 FixedArray, | 561 ElementsKindTraits<FAST_ELEMENTS>, |
358 kPointerSize>(name) {} | 562 kPointerSize>(name) {} |
359 | 563 |
360 static MaybeObject* DeleteCommon(JSObject* obj, | 564 static MaybeObject* DeleteCommon(JSObject* obj, |
361 uint32_t key) { | 565 uint32_t key) { |
362 ASSERT(obj->HasFastElements() || | 566 ASSERT(obj->HasFastElements() || |
363 obj->HasFastSmiOnlyElements() || | 567 obj->HasFastSmiOnlyElements() || |
364 obj->HasFastArgumentsElements()); | 568 obj->HasFastArgumentsElements()); |
365 Heap* heap = obj->GetHeap(); | 569 Heap* heap = obj->GetHeap(); |
366 FixedArray* backing_store = FixedArray::cast(obj->elements()); | 570 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
367 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { | 571 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
(...skipping 28 matching lines...) Expand all Loading... | |
396 } | 600 } |
397 if (4 * num_used <= backing_store->length()) { | 601 if (4 * num_used <= backing_store->length()) { |
398 MaybeObject* result = obj->NormalizeElements(); | 602 MaybeObject* result = obj->NormalizeElements(); |
399 if (result->IsFailure()) return result; | 603 if (result->IsFailure()) return result; |
400 } | 604 } |
401 } | 605 } |
402 } | 606 } |
403 return heap->true_value(); | 607 return heap->true_value(); |
404 } | 608 } |
405 | 609 |
610 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | |
Sven Panne
2012/03/09 08:15:18
This could return Object*, I think, allocations ar
danno
2012/03/09 12:12:35
The allocation of HeapNumbers can fail on the Doub
| |
611 uint32_t from_start, | |
612 FixedArrayBase* to, | |
613 ElementsKind to_kind, | |
614 uint32_t to_start, | |
615 int copy_size) { | |
616 switch (to_kind) { | |
617 case FAST_SMI_ONLY_ELEMENTS: | |
618 case FAST_ELEMENTS: { | |
619 AssertNoAllocation no_gc; | |
620 CopyObjectToObjectElements( | |
621 &no_gc, FixedArray::cast(from), ElementsTraits::Kind, from_start, | |
622 FixedArray::cast(to), to_kind, to_start, copy_size); | |
623 return from; | |
624 } | |
625 default: | |
626 UNREACHABLE(); | |
627 } | |
628 return to->GetHeap()->undefined_value(); | |
629 } | |
630 | |
631 | |
406 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 632 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
407 uint32_t capacity, | 633 uint32_t capacity, |
408 uint32_t length) { | 634 uint32_t length) { |
409 JSObject::SetFastElementsCapacityMode set_capacity_mode = | 635 JSObject::SetFastElementsCapacityMode set_capacity_mode = |
410 obj->HasFastSmiOnlyElements() | 636 obj->HasFastSmiOnlyElements() |
411 ? JSObject::kAllowSmiOnlyElements | 637 ? JSObject::kAllowSmiOnlyElements |
412 : JSObject::kDontAllowSmiOnlyElements; | 638 : JSObject::kDontAllowSmiOnlyElements; |
413 return obj->SetFastElementsCapacityAndLength(capacity, | 639 return obj->SetFastElementsCapacityAndLength(capacity, |
414 length, | 640 length, |
415 set_capacity_mode); | 641 set_capacity_mode); |
416 } | 642 } |
417 | 643 |
418 protected: | 644 protected: |
419 friend class FastElementsAccessor<FastObjectElementsAccessor, | 645 friend class FastElementsAccessor<FastObjectElementsAccessor, |
420 FixedArray, | 646 ElementsKindTraits<FAST_ELEMENTS>, |
421 kPointerSize>; | 647 kPointerSize>; |
422 | 648 |
423 virtual MaybeObject* Delete(JSObject* obj, | 649 virtual MaybeObject* Delete(JSObject* obj, |
424 uint32_t key, | 650 uint32_t key, |
425 JSReceiver::DeleteMode mode) { | 651 JSReceiver::DeleteMode mode) { |
426 return DeleteCommon(obj, key); | 652 return DeleteCommon(obj, key); |
427 } | 653 } |
428 }; | 654 }; |
429 | 655 |
430 | 656 |
431 class FastDoubleElementsAccessor | 657 class FastDoubleElementsAccessor |
432 : public FastElementsAccessor<FastDoubleElementsAccessor, | 658 : public FastElementsAccessor<FastDoubleElementsAccessor, |
433 FixedDoubleArray, | 659 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
434 kDoubleSize> { | 660 kDoubleSize> { |
435 public: | 661 public: |
436 explicit FastDoubleElementsAccessor(const char* name) | 662 explicit FastDoubleElementsAccessor(const char* name) |
437 : FastElementsAccessor<FastDoubleElementsAccessor, | 663 : FastElementsAccessor<FastDoubleElementsAccessor, |
438 FixedDoubleArray, | 664 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
439 kDoubleSize>(name) {} | 665 kDoubleSize>(name) {} |
440 | 666 |
441 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 667 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
442 uint32_t capacity, | 668 uint32_t capacity, |
443 uint32_t length) { | 669 uint32_t length) { |
444 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); | 670 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); |
445 } | 671 } |
446 | 672 |
447 protected: | 673 protected: |
448 friend class ElementsAccessorBase<FastDoubleElementsAccessor, | 674 friend class ElementsAccessorBase<FastDoubleElementsAccessor, |
449 FixedDoubleArray>; | 675 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; |
450 friend class FastElementsAccessor<FastDoubleElementsAccessor, | 676 friend class FastElementsAccessor<FastDoubleElementsAccessor, |
451 FixedDoubleArray, | 677 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
452 kDoubleSize>; | 678 kDoubleSize>; |
453 | 679 |
680 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | |
681 uint32_t from_start, | |
682 FixedArrayBase* to, | |
683 ElementsKind to_kind, | |
684 uint32_t to_start, | |
685 int copy_size) { | |
686 switch (to_kind) { | |
687 case FAST_SMI_ONLY_ELEMENTS: | |
688 case FAST_ELEMENTS: | |
689 return CopyDoubleToObjectElements( | |
690 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), | |
691 to_kind, to_start, copy_size); | |
692 case FAST_DOUBLE_ELEMENTS: | |
693 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, | |
694 FixedDoubleArray::cast(to), | |
695 to_start, copy_size); | |
Jakob Kummerow
2012/03/09 10:09:36
nit: indentation
danno
2012/03/09 12:12:35
Done.
| |
696 return from; | |
697 default: | |
698 UNREACHABLE(); | |
699 } | |
700 return to->GetHeap()->undefined_value(); | |
701 } | |
702 | |
454 virtual MaybeObject* Delete(JSObject* obj, | 703 virtual MaybeObject* Delete(JSObject* obj, |
455 uint32_t key, | 704 uint32_t key, |
456 JSReceiver::DeleteMode mode) { | 705 JSReceiver::DeleteMode mode) { |
457 int length = obj->IsJSArray() | 706 int length = obj->IsJSArray() |
458 ? Smi::cast(JSArray::cast(obj)->length())->value() | 707 ? Smi::cast(JSArray::cast(obj)->length())->value() |
459 : FixedDoubleArray::cast(obj->elements())->length(); | 708 : FixedDoubleArray::cast(obj->elements())->length(); |
460 if (key < static_cast<uint32_t>(length)) { | 709 if (key < static_cast<uint32_t>(length)) { |
461 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); | 710 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); |
462 } | 711 } |
463 return obj->GetHeap()->true_value(); | 712 return obj->GetHeap()->true_value(); |
464 } | 713 } |
465 | 714 |
466 static bool HasElementImpl(Object* receiver, | 715 static bool HasElementImpl(Object* receiver, |
467 JSObject* holder, | 716 JSObject* holder, |
468 uint32_t key, | 717 uint32_t key, |
469 FixedDoubleArray* backing_store) { | 718 FixedDoubleArray* backing_store) { |
470 return !backing_store->is_the_hole(key); | 719 return !backing_store->is_the_hole(key); |
471 } | 720 } |
472 }; | 721 }; |
473 | 722 |
474 | 723 |
475 // Super class for all external element arrays. | 724 // Super class for all external element arrays. |
476 template<typename ExternalElementsAccessorSubclass, | 725 template<typename ExternalElementsAccessorSubclass, |
477 typename ExternalArray> | 726 ElementsKind Kind> |
478 class ExternalElementsAccessor | 727 class ExternalElementsAccessor |
479 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 728 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
480 ExternalArray> { | 729 ElementsKindTraits<Kind> > { |
481 public: | 730 public: |
482 explicit ExternalElementsAccessor(const char* name) | 731 explicit ExternalElementsAccessor(const char* name) |
483 : ElementsAccessorBase<ExternalElementsAccessorSubclass, | 732 : ElementsAccessorBase<ExternalElementsAccessorSubclass, |
484 ExternalArray>(name) {} | 733 ElementsKindTraits<Kind> >(name) {} |
485 | 734 |
486 protected: | 735 protected: |
736 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | |
737 | |
487 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, | 738 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, |
488 ExternalArray>; | 739 ElementsKindTraits<Kind> >; |
489 | 740 |
490 static MaybeObject* GetImpl(Object* receiver, | 741 static MaybeObject* GetImpl(Object* receiver, |
491 JSObject* obj, | 742 JSObject* obj, |
492 uint32_t key, | 743 uint32_t key, |
493 ExternalArray* backing_store) { | 744 BackingStore* backing_store) { |
494 return | 745 return |
495 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 746 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
496 ? backing_store->get(key) | 747 ? backing_store->get(key) |
497 : backing_store->GetHeap()->undefined_value(); | 748 : backing_store->GetHeap()->undefined_value(); |
498 } | 749 } |
499 | 750 |
500 static MaybeObject* SetLengthImpl(JSObject* obj, | 751 static MaybeObject* SetLengthImpl(JSObject* obj, |
501 Object* length, | 752 Object* length, |
502 ExternalArray* backing_store) { | 753 BackingStore* backing_store) { |
503 // External arrays do not support changing their length. | 754 // External arrays do not support changing their length. |
504 UNREACHABLE(); | 755 UNREACHABLE(); |
505 return obj; | 756 return obj; |
506 } | 757 } |
507 | 758 |
508 virtual MaybeObject* Delete(JSObject* obj, | 759 virtual MaybeObject* Delete(JSObject* obj, |
509 uint32_t key, | 760 uint32_t key, |
510 JSReceiver::DeleteMode mode) { | 761 JSReceiver::DeleteMode mode) { |
511 // External arrays always ignore deletes. | 762 // External arrays always ignore deletes. |
512 return obj->GetHeap()->true_value(); | 763 return obj->GetHeap()->true_value(); |
513 } | 764 } |
514 | 765 |
515 static bool HasElementImpl(Object* receiver, | 766 static bool HasElementImpl(Object* receiver, |
516 JSObject* holder, | 767 JSObject* holder, |
517 uint32_t key, | 768 uint32_t key, |
518 ExternalArray* backing_store) { | 769 BackingStore* backing_store) { |
519 uint32_t capacity = | 770 uint32_t capacity = |
520 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); | 771 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); |
521 return key < capacity; | 772 return key < capacity; |
522 } | 773 } |
523 }; | 774 }; |
524 | 775 |
525 | 776 |
526 class ExternalByteElementsAccessor | 777 class ExternalByteElementsAccessor |
527 : public ExternalElementsAccessor<ExternalByteElementsAccessor, | 778 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
528 ExternalByteArray> { | 779 EXTERNAL_BYTE_ELEMENTS> { |
529 public: | 780 public: |
530 explicit ExternalByteElementsAccessor(const char* name) | 781 explicit ExternalByteElementsAccessor(const char* name) |
531 : ExternalElementsAccessor<ExternalByteElementsAccessor, | 782 : ExternalElementsAccessor<ExternalByteElementsAccessor, |
532 ExternalByteArray>(name) {} | 783 EXTERNAL_BYTE_ELEMENTS>(name) {} |
533 }; | 784 }; |
534 | 785 |
535 | 786 |
536 class ExternalUnsignedByteElementsAccessor | 787 class ExternalUnsignedByteElementsAccessor |
537 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, | 788 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, |
538 ExternalUnsignedByteArray> { | 789 EXTERNAL_UNSIGNED_BYTE_ELEMENTS> { |
539 public: | 790 public: |
540 explicit ExternalUnsignedByteElementsAccessor(const char* name) | 791 explicit ExternalUnsignedByteElementsAccessor(const char* name) |
541 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, | 792 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, |
542 ExternalUnsignedByteArray>(name) {} | 793 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {} |
543 }; | 794 }; |
544 | 795 |
545 | 796 |
546 class ExternalShortElementsAccessor | 797 class ExternalShortElementsAccessor |
547 : public ExternalElementsAccessor<ExternalShortElementsAccessor, | 798 : public ExternalElementsAccessor<ExternalShortElementsAccessor, |
548 ExternalShortArray> { | 799 EXTERNAL_SHORT_ELEMENTS> { |
549 public: | 800 public: |
550 explicit ExternalShortElementsAccessor(const char* name) | 801 explicit ExternalShortElementsAccessor(const char* name) |
551 : ExternalElementsAccessor<ExternalShortElementsAccessor, | 802 : ExternalElementsAccessor<ExternalShortElementsAccessor, |
552 ExternalShortArray>(name) {} | 803 EXTERNAL_SHORT_ELEMENTS>(name) {} |
553 }; | 804 }; |
554 | 805 |
555 | 806 |
556 class ExternalUnsignedShortElementsAccessor | 807 class ExternalUnsignedShortElementsAccessor |
557 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, | 808 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, |
558 ExternalUnsignedShortArray> { | 809 EXTERNAL_UNSIGNED_SHORT_ELEMENTS> { |
559 public: | 810 public: |
560 explicit ExternalUnsignedShortElementsAccessor(const char* name) | 811 explicit ExternalUnsignedShortElementsAccessor(const char* name) |
561 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, | 812 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, |
562 ExternalUnsignedShortArray>(name) {} | 813 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {} |
563 }; | 814 }; |
564 | 815 |
565 | 816 |
566 class ExternalIntElementsAccessor | 817 class ExternalIntElementsAccessor |
567 : public ExternalElementsAccessor<ExternalIntElementsAccessor, | 818 : public ExternalElementsAccessor<ExternalIntElementsAccessor, |
568 ExternalIntArray> { | 819 EXTERNAL_INT_ELEMENTS> { |
569 public: | 820 public: |
570 explicit ExternalIntElementsAccessor(const char* name) | 821 explicit ExternalIntElementsAccessor(const char* name) |
571 : ExternalElementsAccessor<ExternalIntElementsAccessor, | 822 : ExternalElementsAccessor<ExternalIntElementsAccessor, |
572 ExternalIntArray>(name) {} | 823 EXTERNAL_INT_ELEMENTS>(name) {} |
573 }; | 824 }; |
574 | 825 |
575 | 826 |
576 class ExternalUnsignedIntElementsAccessor | 827 class ExternalUnsignedIntElementsAccessor |
577 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, | 828 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, |
578 ExternalUnsignedIntArray> { | 829 EXTERNAL_UNSIGNED_INT_ELEMENTS> { |
579 public: | 830 public: |
580 explicit ExternalUnsignedIntElementsAccessor(const char* name) | 831 explicit ExternalUnsignedIntElementsAccessor(const char* name) |
581 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, | 832 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, |
582 ExternalUnsignedIntArray>(name) {} | 833 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {} |
583 }; | 834 }; |
584 | 835 |
585 | 836 |
586 class ExternalFloatElementsAccessor | 837 class ExternalFloatElementsAccessor |
587 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, | 838 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, |
588 ExternalFloatArray> { | 839 EXTERNAL_FLOAT_ELEMENTS> { |
589 public: | 840 public: |
590 explicit ExternalFloatElementsAccessor(const char* name) | 841 explicit ExternalFloatElementsAccessor(const char* name) |
591 : ExternalElementsAccessor<ExternalFloatElementsAccessor, | 842 : ExternalElementsAccessor<ExternalFloatElementsAccessor, |
592 ExternalFloatArray>(name) {} | 843 EXTERNAL_FLOAT_ELEMENTS>(name) {} |
593 }; | 844 }; |
594 | 845 |
595 | 846 |
596 class ExternalDoubleElementsAccessor | 847 class ExternalDoubleElementsAccessor |
597 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, | 848 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, |
598 ExternalDoubleArray> { | 849 EXTERNAL_DOUBLE_ELEMENTS> { |
599 public: | 850 public: |
600 explicit ExternalDoubleElementsAccessor(const char* name) | 851 explicit ExternalDoubleElementsAccessor(const char* name) |
601 : ExternalElementsAccessor<ExternalDoubleElementsAccessor, | 852 : ExternalElementsAccessor<ExternalDoubleElementsAccessor, |
602 ExternalDoubleArray>(name) {} | 853 EXTERNAL_DOUBLE_ELEMENTS>(name) {} |
603 }; | 854 }; |
604 | 855 |
605 | 856 |
606 class PixelElementsAccessor | 857 class PixelElementsAccessor |
607 : public ExternalElementsAccessor<PixelElementsAccessor, | 858 : public ExternalElementsAccessor<PixelElementsAccessor, |
608 ExternalPixelArray> { | 859 EXTERNAL_PIXEL_ELEMENTS> { |
609 public: | 860 public: |
610 explicit PixelElementsAccessor(const char* name) | 861 explicit PixelElementsAccessor(const char* name) |
611 : ExternalElementsAccessor<PixelElementsAccessor, | 862 : ExternalElementsAccessor<PixelElementsAccessor, |
612 ExternalPixelArray>(name) {} | 863 EXTERNAL_PIXEL_ELEMENTS>(name) {} |
613 }; | 864 }; |
614 | 865 |
615 | 866 |
616 class DictionaryElementsAccessor | 867 class DictionaryElementsAccessor |
617 : public ElementsAccessorBase<DictionaryElementsAccessor, | 868 : public ElementsAccessorBase<DictionaryElementsAccessor, |
618 SeededNumberDictionary> { | 869 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
619 public: | 870 public: |
620 explicit DictionaryElementsAccessor(const char* name) | 871 explicit DictionaryElementsAccessor(const char* name) |
621 : ElementsAccessorBase<DictionaryElementsAccessor, | 872 : ElementsAccessorBase<DictionaryElementsAccessor, |
622 SeededNumberDictionary>(name) {} | 873 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
623 | 874 |
624 // Adjusts the length of the dictionary backing store and returns the new | 875 // Adjusts the length of the dictionary backing store and returns the new |
625 // length according to ES5 section 15.4.5.2 behavior. | 876 // length according to ES5 section 15.4.5.2 behavior. |
626 static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, | 877 static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, |
627 JSArray* array, | 878 JSArray* array, |
628 Object* length_object, | 879 Object* length_object, |
629 uint32_t length) { | 880 uint32_t length) { |
630 if (length == 0) { | 881 if (length == 0) { |
631 // If the length of a slow array is reset to zero, we clear | 882 // If the length of a slow array is reset to zero, we clear |
632 // the array and flush backing storage. This has the added | 883 // the array and flush backing storage. This has the added |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
716 Handle<Object> args[2] = { name, holder }; | 967 Handle<Object> args[2] = { name, holder }; |
717 Handle<Object> error = | 968 Handle<Object> error = |
718 isolate->factory()->NewTypeError("strict_delete_property", | 969 isolate->factory()->NewTypeError("strict_delete_property", |
719 HandleVector(args, 2)); | 970 HandleVector(args, 2)); |
720 return isolate->Throw(*error); | 971 return isolate->Throw(*error); |
721 } | 972 } |
722 } | 973 } |
723 return heap->true_value(); | 974 return heap->true_value(); |
724 } | 975 } |
725 | 976 |
977 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | |
978 uint32_t from_start, | |
979 FixedArrayBase* to, | |
980 ElementsKind to_kind, | |
981 uint32_t to_start, | |
982 int copy_size) { | |
983 switch (to_kind) { | |
984 case FAST_SMI_ONLY_ELEMENTS: | |
985 case FAST_ELEMENTS: | |
986 CopyDictionaryToObjectElements( | |
987 SeededNumberDictionary::cast(from), from_start, | |
988 FixedArray::cast(to), to_kind, to_start, copy_size); | |
989 return from; default: | |
Sven Panne
2012/03/09 08:15:18
Layout...
Jakob Kummerow
2012/03/09 10:09:36
nit: new line for "default:" please.
danno
2012/03/09 12:12:35
Done.
danno
2012/03/09 12:12:35
Done.
| |
990 UNREACHABLE(); | |
991 } | |
992 return to->GetHeap()->undefined_value(); | |
993 } | |
994 | |
995 | |
726 protected: | 996 protected: |
727 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 997 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
728 SeededNumberDictionary>; | 998 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
729 | 999 |
730 virtual MaybeObject* Delete(JSObject* obj, | 1000 virtual MaybeObject* Delete(JSObject* obj, |
731 uint32_t key, | 1001 uint32_t key, |
732 JSReceiver::DeleteMode mode) { | 1002 JSReceiver::DeleteMode mode) { |
733 return DeleteCommon(obj, key, mode); | 1003 return DeleteCommon(obj, key, mode); |
734 } | 1004 } |
735 | 1005 |
736 static MaybeObject* GetImpl(Object* receiver, | 1006 static MaybeObject* GetImpl(Object* receiver, |
737 JSObject* obj, | 1007 JSObject* obj, |
738 uint32_t key, | 1008 uint32_t key, |
(...skipping 23 matching lines...) Expand all Loading... | |
762 } | 1032 } |
763 | 1033 |
764 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, | 1034 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, |
765 uint32_t index) { | 1035 uint32_t index) { |
766 Object* key = dict->KeyAt(index); | 1036 Object* key = dict->KeyAt(index); |
767 return Smi::cast(key)->value(); | 1037 return Smi::cast(key)->value(); |
768 } | 1038 } |
769 }; | 1039 }; |
770 | 1040 |
771 | 1041 |
772 class NonStrictArgumentsElementsAccessor | 1042 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< |
773 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1043 NonStrictArgumentsElementsAccessor, |
774 FixedArray> { | 1044 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { |
775 public: | 1045 public: |
776 explicit NonStrictArgumentsElementsAccessor(const char* name) | 1046 explicit NonStrictArgumentsElementsAccessor(const char* name) |
777 : ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1047 : ElementsAccessorBase< |
778 FixedArray>(name) {} | 1048 NonStrictArgumentsElementsAccessor, |
1049 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} | |
779 protected: | 1050 protected: |
780 friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1051 friend class ElementsAccessorBase< |
781 FixedArray>; | 1052 NonStrictArgumentsElementsAccessor, |
Jakob Kummerow
2012/03/09 10:09:36
very nitty nit: 4 spaces indent, not 5 :-)
danno
2012/03/09 12:12:35
Done.
| |
1053 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; | |
782 | 1054 |
783 static MaybeObject* GetImpl(Object* receiver, | 1055 static MaybeObject* GetImpl(Object* receiver, |
784 JSObject* obj, | 1056 JSObject* obj, |
785 uint32_t key, | 1057 uint32_t key, |
786 FixedArray* parameter_map) { | 1058 FixedArray* parameter_map) { |
787 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1059 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
788 if (!probe->IsTheHole()) { | 1060 if (!probe->IsTheHole()) { |
789 Context* context = Context::cast(parameter_map->get(0)); | 1061 Context* context = Context::cast(parameter_map->get(0)); |
790 int context_index = Smi::cast(probe)->value(); | 1062 int context_index = Smi::cast(probe)->value(); |
791 ASSERT(!context->get(context_index)->IsTheHole()); | 1063 ASSERT(!context->get(context_index)->IsTheHole()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
833 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1105 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
834 if (arguments->IsDictionary()) { | 1106 if (arguments->IsDictionary()) { |
835 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 1107 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
836 } else { | 1108 } else { |
837 return FastObjectElementsAccessor::DeleteCommon(obj, key); | 1109 return FastObjectElementsAccessor::DeleteCommon(obj, key); |
838 } | 1110 } |
839 } | 1111 } |
840 return obj->GetHeap()->true_value(); | 1112 return obj->GetHeap()->true_value(); |
841 } | 1113 } |
842 | 1114 |
1115 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | |
1116 uint32_t from_start, | |
1117 FixedArrayBase* to, | |
1118 ElementsKind to_kind, | |
1119 uint32_t to_start, | |
1120 int copy_size) { | |
1121 FixedArray* parameter_map = FixedArray::cast(from); | |
1122 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
1123 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | |
1124 return accessor->CopyElements(NULL, from_start, to, to_kind, | |
1125 to_start, copy_size, arguments); | |
1126 } | |
1127 | |
843 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { | 1128 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { |
844 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1129 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
845 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 1130 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
846 ForArray(arguments)->GetCapacity(arguments)); | 1131 ForArray(arguments)->GetCapacity(arguments)); |
847 } | 1132 } |
848 | 1133 |
849 static uint32_t GetKeyForIndexImpl(FixedArray* dict, | 1134 static uint32_t GetKeyForIndexImpl(FixedArray* dict, |
850 uint32_t index) { | 1135 uint32_t index) { |
851 return index; | 1136 return index; |
852 } | 1137 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 case EXTERNAL_PIXEL_ARRAY_TYPE: | 1191 case EXTERNAL_PIXEL_ARRAY_TYPE: |
907 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; | 1192 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; |
908 default: | 1193 default: |
909 UNREACHABLE(); | 1194 UNREACHABLE(); |
910 return NULL; | 1195 return NULL; |
911 } | 1196 } |
912 } | 1197 } |
913 | 1198 |
914 | 1199 |
915 void ElementsAccessor::InitializeOncePerProcess() { | 1200 void ElementsAccessor::InitializeOncePerProcess() { |
916 // First argument in list is the accessor class, the second argument is can | |
917 // be any arbitrary unique identifier, in this case chosen to be the | |
918 // corresponding enum. Use the fast element handler for smi-only arrays. | |
919 // The implementation is currently identical. Note that the order must match | |
920 // that of the ElementsKind enum for the |accessor_array[]| below to work. | |
921 #define ELEMENTS_LIST(V) \ | |
922 V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS) \ | |
923 V(FastObjectElementsAccessor, FAST_ELEMENTS) \ | |
924 V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS) \ | |
925 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS) \ | |
926 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS) \ | |
927 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS) \ | |
928 V(ExternalUnsignedByteElementsAccessor, EXTERNAL_UNSIGNED_BYTE_ELEMENTS) \ | |
929 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS) \ | |
930 V(ExternalUnsignedShortElementsAccessor, EXTERNAL_UNSIGNED_SHORT_ELEMENTS) \ | |
931 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS) \ | |
932 V(ExternalUnsignedIntElementsAccessor, EXTERNAL_UNSIGNED_INT_ELEMENTS) \ | |
933 V(ExternalFloatElementsAccessor, EXTERNAL_FLOAT_ELEMENTS) \ | |
934 V(ExternalDoubleElementsAccessor, EXTERNAL_DOUBLE_ELEMENTS) \ | |
935 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS) | |
936 | |
937 static struct ConcreteElementsAccessors { | 1201 static struct ConcreteElementsAccessors { |
938 #define ACCESSOR_STRUCT(Class, Name) Class* Name##_handler; | 1202 #define ACCESSOR_STRUCT(Class, Kind, Store) Class* Kind##_handler; |
939 ELEMENTS_LIST(ACCESSOR_STRUCT) | 1203 ELEMENTS_LIST(ACCESSOR_STRUCT) |
940 #undef ACCESSOR_STRUCT | 1204 #undef ACCESSOR_STRUCT |
941 } element_accessors = { | 1205 } element_accessors = { |
942 #define ACCESSOR_INIT(Class, Name) new Class(#Name), | 1206 #define ACCESSOR_INIT(Class, Kind, Store) new Class(#Kind), |
943 ELEMENTS_LIST(ACCESSOR_INIT) | 1207 ELEMENTS_LIST(ACCESSOR_INIT) |
944 #undef ACCESSOR_INIT | 1208 #undef ACCESSOR_INIT |
945 }; | 1209 }; |
946 | 1210 |
947 static ElementsAccessor* accessor_array[] = { | 1211 static ElementsAccessor* accessor_array[] = { |
948 #define ACCESSOR_ARRAY(Class, Name) element_accessors.Name##_handler, | 1212 #define ACCESSOR_ARRAY(Class, Kind, Store) element_accessors.Kind##_handler, |
949 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1213 ELEMENTS_LIST(ACCESSOR_ARRAY) |
950 #undef ACCESSOR_ARRAY | 1214 #undef ACCESSOR_ARRAY |
951 }; | 1215 }; |
952 | 1216 |
953 #undef ELEMENTS_LIST | |
954 | |
955 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 1217 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
956 kElementsKindCount); | 1218 kElementsKindCount); |
957 | 1219 |
958 elements_accessors_ = accessor_array; | 1220 elements_accessors_ = accessor_array; |
959 } | 1221 } |
960 | 1222 |
961 | 1223 |
962 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | 1224 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
963 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>:: | 1225 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, |
1226 ElementsKindTraits>:: | |
964 SetLengthImpl(JSObject* obj, | 1227 SetLengthImpl(JSObject* obj, |
965 Object* length, | 1228 Object* length, |
966 BackingStoreClass* backing_store) { | 1229 typename ElementsKindTraits::BackingStore* backing_store) { |
967 JSArray* array = JSArray::cast(obj); | 1230 JSArray* array = JSArray::cast(obj); |
968 | 1231 |
969 // Fast case: The new length fits into a Smi. | 1232 // Fast case: The new length fits into a Smi. |
970 MaybeObject* maybe_smi_length = length->ToSmi(); | 1233 MaybeObject* maybe_smi_length = length->ToSmi(); |
971 Object* smi_length = Smi::FromInt(0); | 1234 Object* smi_length = Smi::FromInt(0); |
972 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 1235 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
973 const int value = Smi::cast(smi_length)->value(); | 1236 const int value = Smi::cast(smi_length)->value(); |
974 if (value >= 0) { | 1237 if (value >= 0) { |
975 Object* new_length; | 1238 Object* new_length; |
976 MaybeObject* result = ElementsAccessorSubclass:: | 1239 MaybeObject* result = ElementsAccessorSubclass:: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1013 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1276 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
1014 new_backing_store->set(0, length); | 1277 new_backing_store->set(0, length); |
1015 { MaybeObject* result = array->SetContent(new_backing_store); | 1278 { MaybeObject* result = array->SetContent(new_backing_store); |
1016 if (result->IsFailure()) return result; | 1279 if (result->IsFailure()) return result; |
1017 } | 1280 } |
1018 return array; | 1281 return array; |
1019 } | 1282 } |
1020 | 1283 |
1021 | 1284 |
1022 } } // namespace v8::internal | 1285 } } // namespace v8::internal |
OLD | NEW |