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