Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: src/elements.cc

Issue 9638014: Implement efficient element copying in ElementsAccessors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/elements.h ('k') | src/objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698