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