v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
elements.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "objects.h"
31 #include "elements.h"
32 #include "utils.h"
33 
34 
35 // Each concrete ElementsAccessor can handle exactly one ElementsKind,
36 // several abstract ElementsAccessor classes are used to allow sharing
37 // common code.
38 //
39 // Inheritance hierarchy:
40 // - ElementsAccessorBase (abstract)
41 // - FastElementsAccessor (abstract)
42 // - FastSmiOrObjectElementsAccessor
43 // - FastPackedSmiElementsAccessor
44 // - FastHoleySmiElementsAccessor
45 // - FastPackedObjectElementsAccessor
46 // - FastHoleyObjectElementsAccessor
47 // - FastDoubleElementsAccessor
48 // - FastPackedDoubleElementsAccessor
49 // - FastHoleyDoubleElementsAccessor
50 // - ExternalElementsAccessor (abstract)
51 // - ExternalByteElementsAccessor
52 // - ExternalUnsignedByteElementsAccessor
53 // - ExternalShortElementsAccessor
54 // - ExternalUnsignedShortElementsAccessor
55 // - ExternalIntElementsAccessor
56 // - ExternalUnsignedIntElementsAccessor
57 // - ExternalFloatElementsAccessor
58 // - ExternalDoubleElementsAccessor
59 // - PixelElementsAccessor
60 // - DictionaryElementsAccessor
61 // - NonStrictArgumentsElementsAccessor
62 
63 
64 namespace v8 {
65 namespace internal {
66 
67 
68 static const int kPackedSizeNotKnown = -1;
69 
70 
71 // First argument in list is the accessor class, the second argument is the
72 // accessor ElementsKind, and the third is the backing store class. Use the
73 // fast element handler for smi-only arrays. The implementation is currently
74 // identical. Note that the order must match that of the ElementsKind enum for
75 // the |accessor_array[]| below to work.
76 #define ELEMENTS_LIST(V) \
77  V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
78  V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \
79  FixedArray) \
80  V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
81  V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
82  V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \
83  FixedDoubleArray) \
84  V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
85  FixedDoubleArray) \
86  V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
87  SeededNumberDictionary) \
88  V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \
89  FixedArray) \
90  V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \
91  ExternalByteArray) \
92  V(ExternalUnsignedByteElementsAccessor, \
93  EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \
94  V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \
95  ExternalShortArray) \
96  V(ExternalUnsignedShortElementsAccessor, \
97  EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \
98  V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \
99  ExternalIntArray) \
100  V(ExternalUnsignedIntElementsAccessor, \
101  EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \
102  V(ExternalFloatElementsAccessor, \
103  EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \
104  V(ExternalDoubleElementsAccessor, \
105  EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \
106  V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
107 
108 
109 template<ElementsKind Kind> class ElementsKindTraits {
110  public:
112 };
113 
114 #define ELEMENTS_TRAITS(Class, KindParam, Store) \
115 template<> class ElementsKindTraits<KindParam> { \
116  public: \
117  static const ElementsKind Kind = KindParam; \
118  typedef Store BackingStore; \
119 };
121 #undef ELEMENTS_TRAITS
122 
123 
124 ElementsAccessor** ElementsAccessor::elements_accessors_;
125 
126 
127 static bool HasKey(FixedArray* array, Object* key) {
128  int len0 = array->length();
129  for (int i = 0; i < len0; i++) {
130  Object* element = array->get(i);
131  if (element->IsSmi() && element == key) return true;
132  if (element->IsString() &&
133  key->IsString() && String::cast(element)->Equals(String::cast(key))) {
134  return true;
135  }
136  }
137  return false;
138 }
139 
140 
141 static Failure* ThrowArrayLengthRangeError(Heap* heap) {
142  HandleScope scope(heap->isolate());
143  return heap->isolate()->Throw(
144  *heap->isolate()->factory()->NewRangeError("invalid_array_length",
145  HandleVector<Object>(NULL, 0)));
146 }
147 
148 
150  ElementsKind from_kind,
151  uint32_t from_start,
152  FixedArray* to,
153  ElementsKind to_kind,
154  uint32_t to_start,
155  int raw_copy_size) {
156  ASSERT(to->map() != HEAP->fixed_cow_array_map());
157  int copy_size = raw_copy_size;
158  if (raw_copy_size < 0) {
159  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
161  copy_size = Min(from->length() - from_start,
162  to->length() - to_start);
163 #ifdef DEBUG
164  // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
165  // marked with the hole.
167  for (int i = to_start + copy_size; i < to->length(); ++i) {
168  ASSERT(to->get(i)->IsTheHole());
169  }
170  }
171 #endif
172  }
173  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
174  (copy_size + static_cast<int>(from_start)) <= from->length());
175  if (copy_size == 0) return;
178  Address to_address = to->address() + FixedArray::kHeaderSize;
179  Address from_address = from->address() + FixedArray::kHeaderSize;
180  CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
181  reinterpret_cast<Object**>(from_address) + from_start,
182  copy_size);
183  if (IsFastObjectElementsKind(from_kind) &&
184  IsFastObjectElementsKind(to_kind)) {
185  Heap* heap = from->GetHeap();
186  if (!heap->InNewSpace(to)) {
187  heap->RecordWrites(to->address(),
188  to->OffsetOfElementAt(to_start),
189  copy_size);
190  }
191  heap->incremental_marking()->RecordWrites(to);
192  }
193 }
194 
195 
196 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
197  uint32_t from_start,
198  FixedArray* to,
199  ElementsKind to_kind,
200  uint32_t to_start,
201  int raw_copy_size) {
202  int copy_size = raw_copy_size;
203  Heap* heap = from->GetHeap();
204  if (raw_copy_size < 0) {
205  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
207  copy_size = from->max_number_key() + 1 - from_start;
208 #ifdef DEBUG
209  // Fast object arrays cannot be uninitialized. Ensure they are already
210  // marked with the hole.
212  for (int i = to_start + copy_size; i < to->length(); ++i) {
213  ASSERT(to->get(i)->IsTheHole());
214  }
215  }
216 #endif
217  }
218  ASSERT(to != from);
220  if (copy_size == 0) return;
221  uint32_t to_length = to->length();
222  if (to_start + copy_size > to_length) {
223  copy_size = to_length - to_start;
224  }
225  for (int i = 0; i < copy_size; i++) {
226  int entry = from->FindEntry(i + from_start);
227  if (entry != SeededNumberDictionary::kNotFound) {
228  Object* value = from->ValueAt(entry);
229  ASSERT(!value->IsTheHole());
230  to->set(i + to_start, value, SKIP_WRITE_BARRIER);
231  } else {
232  to->set_the_hole(i + to_start);
233  }
234  }
235  if (IsFastObjectElementsKind(to_kind)) {
236  if (!heap->InNewSpace(to)) {
237  heap->RecordWrites(to->address(),
238  to->OffsetOfElementAt(to_start),
239  copy_size);
240  }
241  heap->incremental_marking()->RecordWrites(to);
242  }
243 }
244 
245 
246 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
247  FixedDoubleArray* from,
248  uint32_t from_start,
249  FixedArray* to,
250  ElementsKind to_kind,
251  uint32_t to_start,
252  int raw_copy_size) {
254  int copy_size = raw_copy_size;
255  if (raw_copy_size < 0) {
256  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
258  copy_size = Min(from->length() - from_start,
259  to->length() - to_start);
260 #ifdef DEBUG
261  // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
262  // marked with the hole.
264  for (int i = to_start + copy_size; i < to->length(); ++i) {
265  ASSERT(to->get(i)->IsTheHole());
266  }
267  }
268 #endif
269  }
270  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
271  (copy_size + static_cast<int>(from_start)) <= from->length());
272  if (copy_size == 0) return from;
273  for (int i = 0; i < copy_size; ++i) {
274  if (IsFastSmiElementsKind(to_kind)) {
275  UNIMPLEMENTED();
276  return Failure::Exception();
277  } else {
278  MaybeObject* maybe_value = from->get(i + from_start);
279  Object* value;
281  // Because Double -> Object elements transitions allocate HeapObjects
282  // iteratively, the allocate must succeed within a single GC cycle,
283  // otherwise the retry after the GC will also fail. In order to ensure
284  // that no GC is triggered, allocate HeapNumbers from old space if they
285  // can't be taken from new space.
286  if (!maybe_value->ToObject(&value)) {
287  ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory());
288  Heap* heap = from->GetHeap();
289  MaybeObject* maybe_value_object =
290  heap->AllocateHeapNumber(from->get_scalar(i + from_start),
291  TENURED);
292  if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
293  }
294  to->set(i + to_start, value, UPDATE_WRITE_BARRIER);
295  }
296  }
297  return to;
298 }
299 
300 
301 static void CopyDoubleToDoubleElements(FixedDoubleArray* from,
302  uint32_t from_start,
303  FixedDoubleArray* to,
304  uint32_t to_start,
305  int raw_copy_size) {
306  int copy_size = raw_copy_size;
307  if (raw_copy_size < 0) {
308  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
310  copy_size = Min(from->length() - from_start,
311  to->length() - to_start);
313  for (int i = to_start + copy_size; i < to->length(); ++i) {
314  to->set_the_hole(i);
315  }
316  }
317  }
318  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
319  (copy_size + static_cast<int>(from_start)) <= from->length());
320  if (copy_size == 0) return;
321  Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
322  Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
323  to_address += kDoubleSize * to_start;
324  from_address += kDoubleSize * from_start;
325  int words_per_double = (kDoubleSize / kPointerSize);
326  CopyWords(reinterpret_cast<Object**>(to_address),
327  reinterpret_cast<Object**>(from_address),
328  words_per_double * copy_size);
329 }
330 
331 
332 static void CopySmiToDoubleElements(FixedArray* from,
333  uint32_t from_start,
334  FixedDoubleArray* to,
335  uint32_t to_start,
336  int raw_copy_size) {
337  int copy_size = raw_copy_size;
338  if (raw_copy_size < 0) {
339  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
341  copy_size = from->length() - from_start;
343  for (int i = to_start + copy_size; i < to->length(); ++i) {
344  to->set_the_hole(i);
345  }
346  }
347  }
348  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
349  (copy_size + static_cast<int>(from_start)) <= from->length());
350  if (copy_size == 0) return;
351  Object* the_hole = from->GetHeap()->the_hole_value();
352  for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size);
353  from_start < from_end; from_start++, to_start++) {
354  Object* hole_or_smi = from->get(from_start);
355  if (hole_or_smi == the_hole) {
356  to->set_the_hole(to_start);
357  } else {
358  to->set(to_start, Smi::cast(hole_or_smi)->value());
359  }
360  }
361 }
362 
363 
364 static void CopyPackedSmiToDoubleElements(FixedArray* from,
365  uint32_t from_start,
366  FixedDoubleArray* to,
367  uint32_t to_start,
368  int packed_size,
369  int raw_copy_size) {
370  int copy_size = raw_copy_size;
371  uint32_t to_end;
372  if (raw_copy_size < 0) {
373  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
375  copy_size = from->length() - from_start;
377  to_end = to->length();
378  } else {
379  to_end = to_start + static_cast<uint32_t>(copy_size);
380  }
381  } else {
382  to_end = to_start + static_cast<uint32_t>(copy_size);
383  }
384  ASSERT(static_cast<int>(to_end) <= to->length());
385  ASSERT(packed_size >= 0 && packed_size <= copy_size);
386  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
387  (copy_size + static_cast<int>(from_start)) <= from->length());
388  if (copy_size == 0) return;
389  for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
390  from_start < from_end; from_start++, to_start++) {
391  Object* smi = from->get(from_start);
392  ASSERT(!smi->IsTheHole());
393  to->set(to_start, Smi::cast(smi)->value());
394  }
395 
396  while (to_start < to_end) {
397  to->set_the_hole(to_start++);
398  }
399 }
400 
401 
402 static void CopyObjectToDoubleElements(FixedArray* from,
403  uint32_t from_start,
404  FixedDoubleArray* to,
405  uint32_t to_start,
406  int raw_copy_size) {
407  int copy_size = raw_copy_size;
408  if (raw_copy_size < 0) {
409  ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
411  copy_size = from->length() - from_start;
413  for (int i = to_start + copy_size; i < to->length(); ++i) {
414  to->set_the_hole(i);
415  }
416  }
417  }
418  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
419  (copy_size + static_cast<int>(from_start)) <= from->length());
420  if (copy_size == 0) return;
421  Object* the_hole = from->GetHeap()->the_hole_value();
422  for (uint32_t from_end = from_start + copy_size;
423  from_start < from_end; from_start++, to_start++) {
424  Object* hole_or_object = from->get(from_start);
425  if (hole_or_object == the_hole) {
426  to->set_the_hole(to_start);
427  } else {
428  to->set(to_start, hole_or_object->Number());
429  }
430  }
431 }
432 
433 
434 static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from,
435  uint32_t from_start,
436  FixedDoubleArray* to,
437  uint32_t to_start,
438  int raw_copy_size) {
439  int copy_size = raw_copy_size;
440  if (copy_size < 0) {
441  ASSERT(copy_size == ElementsAccessor::kCopyToEnd ||
443  copy_size = from->max_number_key() + 1 - from_start;
445  for (int i = to_start + copy_size; i < to->length(); ++i) {
446  to->set_the_hole(i);
447  }
448  }
449  }
450  if (copy_size == 0) return;
451  uint32_t to_length = to->length();
452  if (to_start + copy_size > to_length) {
453  copy_size = to_length - to_start;
454  }
455  for (int i = 0; i < copy_size; i++) {
456  int entry = from->FindEntry(i + from_start);
457  if (entry != SeededNumberDictionary::kNotFound) {
458  to->set(i + to_start, from->ValueAt(entry)->Number());
459  } else {
460  to->set_the_hole(i + to_start);
461  }
462  }
463 }
464 
465 
466 // Base class for element handler implementations. Contains the
467 // the common logic for objects with different ElementsKinds.
468 // Subclasses must specialize method for which the element
469 // implementation differs from the base class implementation.
470 //
471 // This class is intended to be used in the following way:
472 //
473 // class SomeElementsAccessor :
474 // public ElementsAccessorBase<SomeElementsAccessor,
475 // BackingStoreClass> {
476 // ...
477 // }
478 //
479 // This is an example of the Curiously Recurring Template Pattern (see
480 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
481 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
482 // specialization of SomeElementsAccessor methods).
483 template <typename ElementsAccessorSubclass,
484  typename ElementsTraitsParam>
486  protected:
487  explicit ElementsAccessorBase(const char* name)
488  : ElementsAccessor(name) { }
489 
490  typedef ElementsTraitsParam ElementsTraits;
491  typedef typename ElementsTraitsParam::BackingStore BackingStore;
492 
493  virtual ElementsKind kind() const { return ElementsTraits::Kind; }
494 
495  static void ValidateContents(JSObject* holder, int length) {
496  }
497 
498  static void ValidateImpl(JSObject* holder) {
499  FixedArrayBase* fixed_array_base = holder->elements();
500  // When objects are first allocated, its elements are Failures.
501  if (fixed_array_base->IsFailure()) return;
502  if (!fixed_array_base->IsHeapObject()) return;
503  Map* map = fixed_array_base->map();
504  // Arrays that have been shifted in place can't be verified.
505  Heap* heap = holder->GetHeap();
506  if (map == heap->raw_unchecked_one_pointer_filler_map() ||
507  map == heap->raw_unchecked_two_pointer_filler_map() ||
508  map == heap->free_space_map()) {
509  return;
510  }
511  int length = 0;
512  if (holder->IsJSArray()) {
513  Object* length_obj = JSArray::cast(holder)->length();
514  if (length_obj->IsSmi()) {
515  length = Smi::cast(length_obj)->value();
516  }
517  } else {
518  length = fixed_array_base->length();
519  }
520  ElementsAccessorSubclass::ValidateContents(holder, length);
521  }
522 
523  virtual void Validate(JSObject* holder) {
524  ElementsAccessorSubclass::ValidateImpl(holder);
525  }
526 
527  static bool HasElementImpl(Object* receiver,
528  JSObject* holder,
529  uint32_t key,
530  BackingStore* backing_store) {
531  MaybeObject* element =
532  ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store);
533  return !element->IsTheHole();
534  }
535 
536  virtual bool HasElement(Object* receiver,
537  JSObject* holder,
538  uint32_t key,
539  FixedArrayBase* backing_store) {
540  if (backing_store == NULL) {
541  backing_store = holder->elements();
542  }
543  return ElementsAccessorSubclass::HasElementImpl(
544  receiver, holder, key, BackingStore::cast(backing_store));
545  }
546 
547  MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver,
548  JSObject* holder,
549  uint32_t key,
550  FixedArrayBase* backing_store) {
551  if (backing_store == NULL) {
552  backing_store = holder->elements();
553  }
554  return ElementsAccessorSubclass::GetImpl(
555  receiver, holder, key, BackingStore::cast(backing_store));
556  }
557 
558  MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
559  JSObject* obj,
560  uint32_t key,
561  BackingStore* backing_store) {
562  return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store))
563  ? backing_store->get(key)
564  : backing_store->GetHeap()->the_hole_value();
565  }
566 
567  MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array,
568  Object* length) {
569  return ElementsAccessorSubclass::SetLengthImpl(
570  array, length, BackingStore::cast(array->elements()));
571  }
572 
573  MUST_USE_RESULT static MaybeObject* SetLengthImpl(
574  JSObject* obj,
575  Object* length,
576  BackingStore* backing_store);
577 
578  MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(
579  JSArray* array,
580  int capacity,
581  int length) {
582  return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
583  array,
584  capacity,
585  length);
586  }
587 
589  JSObject* obj,
590  int capacity,
591  int length) {
592  UNIMPLEMENTED();
593  return obj;
594  }
595 
596  MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
597  uint32_t key,
598  JSReceiver::DeleteMode mode) = 0;
599 
601  uint32_t from_start,
602  FixedArrayBase* to,
603  ElementsKind to_kind,
604  uint32_t to_start,
605  int packed_size,
606  int copy_size) {
607  UNREACHABLE();
608  return NULL;
609  }
610 
611  MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder,
612  uint32_t from_start,
613  FixedArrayBase* to,
614  ElementsKind to_kind,
615  uint32_t to_start,
616  int copy_size,
617  FixedArrayBase* from) {
618  int packed_size = kPackedSizeNotKnown;
619  if (from == NULL) {
620  from = from_holder->elements();
621  }
622 
623  if (from_holder) {
624  ElementsKind elements_kind = from_holder->GetElementsKind();
625  bool is_packed = IsFastPackedElementsKind(elements_kind) &&
626  from_holder->IsJSArray();
627  if (is_packed) {
628  packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value();
629  if (copy_size >= 0 && packed_size > copy_size) {
630  packed_size = copy_size;
631  }
632  }
633  }
634  if (from->length() == 0) {
635  return from;
636  }
637  return ElementsAccessorSubclass::CopyElementsImpl(
638  from, from_start, to, to_kind, to_start, packed_size, copy_size);
639  }
640 
642  Object* receiver,
643  JSObject* holder,
644  FixedArray* to,
645  FixedArrayBase* from) {
646  int len0 = to->length();
647 #ifdef DEBUG
649  for (int i = 0; i < len0; i++) {
650  ASSERT(!to->get(i)->IsTheHole());
651  }
652  }
653 #endif
654  if (from == NULL) {
655  from = holder->elements();
656  }
657  BackingStore* backing_store = BackingStore::cast(from);
658  uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store);
659 
660  // Optimize if 'other' is empty.
661  // We cannot optimize if 'this' is empty, as other may have holes.
662  if (len1 == 0) return to;
663 
664  // Compute how many elements are not in other.
665  uint32_t extra = 0;
666  for (uint32_t y = 0; y < len1; y++) {
667  uint32_t key =
668  ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
669  if (ElementsAccessorSubclass::HasElementImpl(
670  receiver, holder, key, backing_store)) {
671  MaybeObject* maybe_value =
672  ElementsAccessorSubclass::GetImpl(receiver, holder,
673  key, backing_store);
674  Object* value;
675  if (!maybe_value->ToObject(&value)) return maybe_value;
676  ASSERT(!value->IsTheHole());
677  if (!HasKey(to, value)) {
678  extra++;
679  }
680  }
681  }
682 
683  if (extra == 0) return to;
684 
685  // Allocate the result
686  FixedArray* result;
687  MaybeObject* maybe_obj =
688  backing_store->GetHeap()->AllocateFixedArray(len0 + extra);
689  if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
690 
691  // Fill in the content
692  {
693  AssertNoAllocation no_gc;
694  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
695  for (int i = 0; i < len0; i++) {
696  Object* e = to->get(i);
697  ASSERT(e->IsString() || e->IsNumber());
698  result->set(i, e, mode);
699  }
700  }
701  // Fill in the extra values.
702  uint32_t index = 0;
703  for (uint32_t y = 0; y < len1; y++) {
704  uint32_t key =
705  ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
706  if (ElementsAccessorSubclass::HasElementImpl(
707  receiver, holder, key, backing_store)) {
708  MaybeObject* maybe_value =
709  ElementsAccessorSubclass::GetImpl(receiver, holder,
710  key, backing_store);
711  Object* value;
712  if (!maybe_value->ToObject(&value)) return maybe_value;
713  if (!value->IsTheHole() && !HasKey(to, value)) {
714  result->set(len0 + index, value);
715  index++;
716  }
717  }
718  }
719  ASSERT(extra == index);
720  return result;
721  }
722 
723  protected:
724  static uint32_t GetCapacityImpl(BackingStore* backing_store) {
725  return backing_store->length();
726  }
727 
728  virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
729  return ElementsAccessorSubclass::GetCapacityImpl(
730  BackingStore::cast(backing_store));
731  }
732 
733  static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
734  uint32_t index) {
735  return index;
736  }
737 
738  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
739  uint32_t index) {
740  return ElementsAccessorSubclass::GetKeyForIndexImpl(
741  BackingStore::cast(backing_store), index);
742  }
743 
744  private:
745  DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
746 };
747 
748 
749 // Super class for all fast element arrays.
750 template<typename FastElementsAccessorSubclass,
751  typename KindTraits,
752  int ElementSize>
754  : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
755  public:
756  explicit FastElementsAccessor(const char* name)
757  : ElementsAccessorBase<FastElementsAccessorSubclass,
758  KindTraits>(name) {}
759  protected:
760  friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
762 
763  typedef typename KindTraits::BackingStore BackingStore;
764 
765  // Adjusts the length of the fast backing store or returns the new length or
766  // undefined in case conversion to a slow backing store should be performed.
767  static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store,
768  JSArray* array,
769  Object* length_object,
770  uint32_t length) {
771  uint32_t old_capacity = backing_store->length();
772  Object* old_length = array->length();
773  bool same_size = old_length->IsSmi() &&
774  static_cast<uint32_t>(Smi::cast(old_length)->value()) == length;
775  ElementsKind kind = array->GetElementsKind();
776 
777  if (!same_size && IsFastElementsKind(kind) &&
778  !IsFastHoleyElementsKind(kind)) {
779  kind = GetHoleyElementsKind(kind);
780  MaybeObject* maybe_obj = array->TransitionElementsKind(kind);
781  if (maybe_obj->IsFailure()) return maybe_obj;
782  }
783 
784  // Check whether the backing store should be shrunk.
785  if (length <= old_capacity) {
786  if (array->HasFastSmiOrObjectElements()) {
787  MaybeObject* maybe_obj = array->EnsureWritableFastElements();
788  if (!maybe_obj->To(&backing_store)) return maybe_obj;
789  }
790  if (2 * length <= old_capacity) {
791  // If more than half the elements won't be used, trim the array.
792  if (length == 0) {
793  array->initialize_elements();
794  } else {
795  backing_store->set_length(length);
796  Address filler_start = backing_store->address() +
797  BackingStore::OffsetOfElementAt(length);
798  int filler_size = (old_capacity - length) * ElementSize;
799  array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
800  }
801  } else {
802  // Otherwise, fill the unused tail with holes.
803  int old_length = FastD2IChecked(array->length()->Number());
804  for (int i = length; i < old_length; i++) {
805  backing_store->set_the_hole(i);
806  }
807  }
808  return length_object;
809  }
810 
811  // Check whether the backing store should be expanded.
812  uint32_t min = JSObject::NewElementsCapacity(old_capacity);
813  uint32_t new_capacity = length > min ? length : min;
814  if (!array->ShouldConvertToSlowElements(new_capacity)) {
815  MaybeObject* result = FastElementsAccessorSubclass::
816  SetFastElementsCapacityAndLength(array, new_capacity, length);
817  if (result->IsFailure()) return result;
818  array->ValidateElements();
819  return length_object;
820  }
821 
822  // Request conversion to slow elements.
823  return array->GetHeap()->undefined_value();
824  }
825 
826  static MaybeObject* DeleteCommon(JSObject* obj,
827  uint32_t key,
828  JSReceiver::DeleteMode mode) {
830  obj->HasFastDoubleElements() ||
831  obj->HasFastArgumentsElements());
832  typename KindTraits::BackingStore* backing_store =
833  KindTraits::BackingStore::cast(obj->elements());
834  Heap* heap = obj->GetHeap();
835  if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
836  backing_store =
837  KindTraits::BackingStore::cast(
838  FixedArray::cast(backing_store)->get(1));
839  } else {
840  ElementsKind kind = KindTraits::Kind;
841  if (IsFastPackedElementsKind(kind)) {
842  MaybeObject* transitioned =
844  if (transitioned->IsFailure()) return transitioned;
845  }
846  if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
847  Object* writable;
848  MaybeObject* maybe = obj->EnsureWritableFastElements();
849  if (!maybe->ToObject(&writable)) return maybe;
850  backing_store = KindTraits::BackingStore::cast(writable);
851  }
852  }
853  uint32_t length = static_cast<uint32_t>(
854  obj->IsJSArray()
855  ? Smi::cast(JSArray::cast(obj)->length())->value()
856  : backing_store->length());
857  if (key < length) {
858  backing_store->set_the_hole(key);
859  // If an old space backing store is larger than a certain size and
860  // has too few used values, normalize it.
861  // To avoid doing the check on every delete we require at least
862  // one adjacent hole to the value being deleted.
863  const int kMinLengthForSparsenessCheck = 64;
864  if (backing_store->length() >= kMinLengthForSparsenessCheck &&
865  !heap->InNewSpace(backing_store) &&
866  ((key > 0 && backing_store->is_the_hole(key - 1)) ||
867  (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
868  int num_used = 0;
869  for (int i = 0; i < backing_store->length(); ++i) {
870  if (!backing_store->is_the_hole(i)) ++num_used;
871  // Bail out early if more than 1/4 is used.
872  if (4 * num_used > backing_store->length()) break;
873  }
874  if (4 * num_used <= backing_store->length()) {
875  MaybeObject* result = obj->NormalizeElements();
876  if (result->IsFailure()) return result;
877  }
878  }
879  }
880  return heap->true_value();
881  }
882 
883  virtual MaybeObject* Delete(JSObject* obj,
884  uint32_t key,
885  JSReceiver::DeleteMode mode) {
886  return DeleteCommon(obj, key, mode);
887  }
888 
889  static bool HasElementImpl(
890  Object* receiver,
891  JSObject* holder,
892  uint32_t key,
893  typename KindTraits::BackingStore* backing_store) {
894  if (key >= static_cast<uint32_t>(backing_store->length())) {
895  return false;
896  }
897  return !backing_store->is_the_hole(key);
898  }
899 
900  static void ValidateContents(JSObject* holder, int length) {
901 #if DEBUG
902  FixedArrayBase* elements = holder->elements();
903  Heap* heap = elements->GetHeap();
904  Map* map = elements->map();
905  ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
906  (map == heap->fixed_array_map() ||
907  map == heap->fixed_cow_array_map())) ||
908  (IsFastDoubleElementsKind(KindTraits::Kind) ==
909  ((map == heap->fixed_array_map() && length == 0) ||
910  map == heap->fixed_double_array_map())));
911  for (int i = 0; i < length; i++) {
912  typename KindTraits::BackingStore* backing_store =
913  KindTraits::BackingStore::cast(elements);
914  ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) ||
915  static_cast<Object*>(backing_store->get(i))->IsSmi()) ||
916  (IsFastHoleyElementsKind(KindTraits::Kind) ==
917  backing_store->is_the_hole(i)));
918  }
919 #endif
920  }
921 };
922 
923 
924 template<typename FastElementsAccessorSubclass,
925  typename KindTraits>
927  : public FastElementsAccessor<FastElementsAccessorSubclass,
928  KindTraits,
929  kPointerSize> {
930  public:
931  explicit FastSmiOrObjectElementsAccessor(const char* name)
932  : FastElementsAccessor<FastElementsAccessorSubclass,
933  KindTraits,
934  kPointerSize>(name) {}
935 
936  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
937  uint32_t from_start,
938  FixedArrayBase* to,
939  ElementsKind to_kind,
940  uint32_t to_start,
941  int packed_size,
942  int copy_size) {
943  if (IsFastSmiOrObjectElementsKind(to_kind)) {
945  FixedArray::cast(from), KindTraits::Kind, from_start,
946  FixedArray::cast(to), to_kind, to_start, copy_size);
947  } else if (IsFastDoubleElementsKind(to_kind)) {
948  if (IsFastSmiElementsKind(KindTraits::Kind)) {
949  if (IsFastPackedElementsKind(KindTraits::Kind) &&
950  packed_size != kPackedSizeNotKnown) {
951  CopyPackedSmiToDoubleElements(
952  FixedArray::cast(from), from_start,
953  FixedDoubleArray::cast(to), to_start,
954  packed_size, copy_size);
955  } else {
956  CopySmiToDoubleElements(
957  FixedArray::cast(from), from_start,
958  FixedDoubleArray::cast(to), to_start, copy_size);
959  }
960  } else {
961  CopyObjectToDoubleElements(
962  FixedArray::cast(from), from_start,
963  FixedDoubleArray::cast(to), to_start, copy_size);
964  }
965  } else {
966  UNREACHABLE();
967  }
968  return to->GetHeap()->undefined_value();
969  }
970 
971 
972  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
973  uint32_t capacity,
974  uint32_t length) {
975  JSObject::SetFastElementsCapacitySmiMode set_capacity_mode =
976  obj->HasFastSmiElements()
979  return obj->SetFastElementsCapacityAndLength(capacity,
980  length,
981  set_capacity_mode);
982  }
983 };
984 
985 
988  FastPackedSmiElementsAccessor,
989  ElementsKindTraits<FAST_SMI_ELEMENTS> > {
990  public:
991  explicit FastPackedSmiElementsAccessor(const char* name)
995 };
996 
997 
1000  FastHoleySmiElementsAccessor,
1001  ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > {
1002  public:
1003  explicit FastHoleySmiElementsAccessor(const char* name)
1007 };
1008 
1009 
1012  FastPackedObjectElementsAccessor,
1013  ElementsKindTraits<FAST_ELEMENTS> > {
1014  public:
1018  ElementsKindTraits<FAST_ELEMENTS> >(name) {}
1019 };
1020 
1021 
1024  FastHoleyObjectElementsAccessor,
1025  ElementsKindTraits<FAST_HOLEY_ELEMENTS> > {
1026  public:
1031 };
1032 
1033 
1034 template<typename FastElementsAccessorSubclass,
1035  typename KindTraits>
1037  : public FastElementsAccessor<FastElementsAccessorSubclass,
1038  KindTraits,
1039  kDoubleSize> {
1040  public:
1041  explicit FastDoubleElementsAccessor(const char* name)
1042  : FastElementsAccessor<FastElementsAccessorSubclass,
1043  KindTraits,
1044  kDoubleSize>(name) {}
1045 
1046  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
1047  uint32_t capacity,
1048  uint32_t length) {
1049  return obj->SetFastDoubleElementsCapacityAndLength(capacity,
1050  length);
1051  }
1052 
1053  protected:
1054  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
1055  uint32_t from_start,
1056  FixedArrayBase* to,
1057  ElementsKind to_kind,
1058  uint32_t to_start,
1059  int packed_size,
1060  int copy_size) {
1061  switch (to_kind) {
1062  case FAST_SMI_ELEMENTS:
1063  case FAST_ELEMENTS:
1065  case FAST_HOLEY_ELEMENTS:
1066  return CopyDoubleToObjectElements(
1067  FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
1068  to_kind, to_start, copy_size);
1069  case FAST_DOUBLE_ELEMENTS:
1071  CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
1073  to_start, copy_size);
1074  return from;
1075  default:
1076  UNREACHABLE();
1077  }
1078  return to->GetHeap()->undefined_value();
1079  }
1080 };
1081 
1082 
1084  : public FastDoubleElementsAccessor<
1085  FastPackedDoubleElementsAccessor,
1086  ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > {
1087  public:
1088  friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor,
1092  FastPackedDoubleElementsAccessor,
1094 };
1095 
1096 
1098  : public FastDoubleElementsAccessor<
1099  FastHoleyDoubleElementsAccessor,
1100  ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > {
1101  public:
1102  friend class ElementsAccessorBase<
1103  FastHoleyDoubleElementsAccessor,
1107  FastHoleyDoubleElementsAccessor,
1109 };
1110 
1111 
1112 // Super class for all external element arrays.
1113 template<typename ExternalElementsAccessorSubclass,
1114  ElementsKind Kind>
1116  : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
1117  ElementsKindTraits<Kind> > {
1118  public:
1119  explicit ExternalElementsAccessor(const char* name)
1120  : ElementsAccessorBase<ExternalElementsAccessorSubclass,
1121  ElementsKindTraits<Kind> >(name) {}
1122 
1123  protected:
1125 
1126  friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
1128 
1129  MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
1130  JSObject* obj,
1131  uint32_t key,
1132  BackingStore* backing_store) {
1133  return
1134  key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
1135  ? backing_store->get(key)
1136  : backing_store->GetHeap()->undefined_value();
1137  }
1138 
1139  MUST_USE_RESULT static MaybeObject* SetLengthImpl(
1140  JSObject* obj,
1141  Object* length,
1142  BackingStore* backing_store) {
1143  // External arrays do not support changing their length.
1144  UNREACHABLE();
1145  return obj;
1146  }
1147 
1148  MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1149  uint32_t key,
1150  JSReceiver::DeleteMode mode) {
1151  // External arrays always ignore deletes.
1152  return obj->GetHeap()->true_value();
1153  }
1154 
1155  static bool HasElementImpl(Object* receiver,
1156  JSObject* holder,
1157  uint32_t key,
1158  BackingStore* backing_store) {
1159  uint32_t capacity =
1160  ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
1161  return key < capacity;
1162  }
1163 };
1164 
1165 
1167  : public ExternalElementsAccessor<ExternalByteElementsAccessor,
1168  EXTERNAL_BYTE_ELEMENTS> {
1169  public:
1170  explicit ExternalByteElementsAccessor(const char* name)
1172  EXTERNAL_BYTE_ELEMENTS>(name) {}
1173 };
1174 
1175 
1177  : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
1178  EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
1179  public:
1183 };
1184 
1185 
1187  : public ExternalElementsAccessor<ExternalShortElementsAccessor,
1188  EXTERNAL_SHORT_ELEMENTS> {
1189  public:
1190  explicit ExternalShortElementsAccessor(const char* name)
1192  EXTERNAL_SHORT_ELEMENTS>(name) {}
1193 };
1194 
1195 
1197  : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
1198  EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
1199  public:
1203 };
1204 
1205 
1207  : public ExternalElementsAccessor<ExternalIntElementsAccessor,
1208  EXTERNAL_INT_ELEMENTS> {
1209  public:
1210  explicit ExternalIntElementsAccessor(const char* name)
1212  EXTERNAL_INT_ELEMENTS>(name) {}
1213 };
1214 
1215 
1217  : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
1218  EXTERNAL_UNSIGNED_INT_ELEMENTS> {
1219  public:
1223 };
1224 
1225 
1227  : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
1228  EXTERNAL_FLOAT_ELEMENTS> {
1229  public:
1230  explicit ExternalFloatElementsAccessor(const char* name)
1232  EXTERNAL_FLOAT_ELEMENTS>(name) {}
1233 };
1234 
1235 
1237  : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
1238  EXTERNAL_DOUBLE_ELEMENTS> {
1239  public:
1240  explicit ExternalDoubleElementsAccessor(const char* name)
1242  EXTERNAL_DOUBLE_ELEMENTS>(name) {}
1243 };
1244 
1245 
1247  : public ExternalElementsAccessor<PixelElementsAccessor,
1248  EXTERNAL_PIXEL_ELEMENTS> {
1249  public:
1250  explicit PixelElementsAccessor(const char* name)
1252  EXTERNAL_PIXEL_ELEMENTS>(name) {}
1253 };
1254 
1255 
1257  : public ElementsAccessorBase<DictionaryElementsAccessor,
1258  ElementsKindTraits<DICTIONARY_ELEMENTS> > {
1259  public:
1260  explicit DictionaryElementsAccessor(const char* name)
1263 
1264  // Adjusts the length of the dictionary backing store and returns the new
1265  // length according to ES5 section 15.4.5.2 behavior.
1267  SeededNumberDictionary* dict,
1268  JSArray* array,
1269  Object* length_object,
1270  uint32_t length) {
1271  Heap* heap = array->GetHeap();
1272  int capacity = dict->Capacity();
1273  uint32_t new_length = length;
1274  uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
1275  if (new_length < old_length) {
1276  // Find last non-deletable element in range of elements to be
1277  // deleted and adjust range accordingly.
1278  for (int i = 0; i < capacity; i++) {
1279  Object* key = dict->KeyAt(i);
1280  if (key->IsNumber()) {
1281  uint32_t number = static_cast<uint32_t>(key->Number());
1282  if (new_length <= number && number < old_length) {
1283  PropertyDetails details = dict->DetailsAt(i);
1284  if (details.IsDontDelete()) new_length = number + 1;
1285  }
1286  }
1287  }
1288  if (new_length != length) {
1289  MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
1290  if (!maybe_object->To(&length_object)) return maybe_object;
1291  }
1292  }
1293 
1294  if (new_length == 0) {
1295  // If the length of a slow array is reset to zero, we clear
1296  // the array and flush backing storage. This has the added
1297  // benefit that the array returns to fast mode.
1298  Object* obj;
1299  MaybeObject* maybe_obj = array->ResetElements();
1300  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1301  } else {
1302  // Remove elements that should be deleted.
1303  int removed_entries = 0;
1304  Object* the_hole_value = heap->the_hole_value();
1305  for (int i = 0; i < capacity; i++) {
1306  Object* key = dict->KeyAt(i);
1307  if (key->IsNumber()) {
1308  uint32_t number = static_cast<uint32_t>(key->Number());
1309  if (new_length <= number && number < old_length) {
1310  dict->SetEntry(i, the_hole_value, the_hole_value);
1311  removed_entries++;
1312  }
1313  }
1314  }
1315 
1316  // Update the number of elements.
1317  dict->ElementsRemoved(removed_entries);
1318  }
1319  return length_object;
1320  }
1321 
1322  MUST_USE_RESULT static MaybeObject* DeleteCommon(
1323  JSObject* obj,
1324  uint32_t key,
1325  JSReceiver::DeleteMode mode) {
1326  Isolate* isolate = obj->GetIsolate();
1327  Heap* heap = isolate->heap();
1328  FixedArray* backing_store = FixedArray::cast(obj->elements());
1329  bool is_arguments =
1331  if (is_arguments) {
1332  backing_store = FixedArray::cast(backing_store->get(1));
1333  }
1334  SeededNumberDictionary* dictionary =
1335  SeededNumberDictionary::cast(backing_store);
1336  int entry = dictionary->FindEntry(key);
1337  if (entry != SeededNumberDictionary::kNotFound) {
1338  Object* result = dictionary->DeleteProperty(entry, mode);
1339  if (result == heap->false_value()) {
1340  if (mode == JSObject::STRICT_DELETION) {
1341  // Deleting a non-configurable property in strict mode.
1342  HandleScope scope(isolate);
1343  Handle<Object> holder(obj);
1344  Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
1345  Handle<Object> args[2] = { name, holder };
1346  Handle<Object> error =
1347  isolate->factory()->NewTypeError("strict_delete_property",
1348  HandleVector(args, 2));
1349  return isolate->Throw(*error);
1350  }
1351  return heap->false_value();
1352  }
1353  MaybeObject* maybe_elements = dictionary->Shrink(key);
1354  FixedArray* new_elements = NULL;
1355  if (!maybe_elements->To(&new_elements)) {
1356  return maybe_elements;
1357  }
1358  if (is_arguments) {
1359  FixedArray::cast(obj->elements())->set(1, new_elements);
1360  } else {
1361  obj->set_elements(new_elements);
1362  }
1363  }
1364  return heap->true_value();
1365  }
1366 
1368  uint32_t from_start,
1369  FixedArrayBase* to,
1370  ElementsKind to_kind,
1371  uint32_t to_start,
1372  int packed_size,
1373  int copy_size) {
1374  switch (to_kind) {
1375  case FAST_SMI_ELEMENTS:
1376  case FAST_ELEMENTS:
1378  case FAST_HOLEY_ELEMENTS:
1379  CopyDictionaryToObjectElements(
1380  SeededNumberDictionary::cast(from), from_start,
1381  FixedArray::cast(to), to_kind, to_start, copy_size);
1382  return from;
1383  case FAST_DOUBLE_ELEMENTS:
1385  CopyDictionaryToDoubleElements(
1386  SeededNumberDictionary::cast(from), from_start,
1387  FixedDoubleArray::cast(to), to_start, copy_size);
1388  return from;
1389  default:
1390  UNREACHABLE();
1391  }
1392  return to->GetHeap()->undefined_value();
1393  }
1394 
1395 
1396  protected:
1399 
1400  MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1401  uint32_t key,
1402  JSReceiver::DeleteMode mode) {
1403  return DeleteCommon(obj, key, mode);
1404  }
1405 
1406  MUST_USE_RESULT static MaybeObject* GetImpl(
1407  Object* receiver,
1408  JSObject* obj,
1409  uint32_t key,
1410  SeededNumberDictionary* backing_store) {
1411  int entry = backing_store->FindEntry(key);
1412  if (entry != SeededNumberDictionary::kNotFound) {
1413  Object* element = backing_store->ValueAt(entry);
1414  PropertyDetails details = backing_store->DetailsAt(entry);
1415  if (details.type() == CALLBACKS) {
1416  return obj->GetElementWithCallback(receiver,
1417  element,
1418  key,
1419  obj);
1420  } else {
1421  return element;
1422  }
1423  }
1424  return obj->GetHeap()->the_hole_value();
1425  }
1426 
1427  static bool HasElementImpl(Object* receiver,
1428  JSObject* holder,
1429  uint32_t key,
1430  SeededNumberDictionary* backing_store) {
1431  return backing_store->FindEntry(key) !=
1433  }
1434 
1436  uint32_t index) {
1437  Object* key = dict->KeyAt(index);
1438  return Smi::cast(key)->value();
1439  }
1440 };
1441 
1442 
1444  NonStrictArgumentsElementsAccessor,
1445  ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
1446  public:
1451  protected:
1452  friend class ElementsAccessorBase<
1455 
1456  MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
1457  JSObject* obj,
1458  uint32_t key,
1459  FixedArray* parameter_map) {
1460  Object* probe = GetParameterMapArg(obj, parameter_map, key);
1461  if (!probe->IsTheHole()) {
1462  Context* context = Context::cast(parameter_map->get(0));
1463  int context_index = Smi::cast(probe)->value();
1464  ASSERT(!context->get(context_index)->IsTheHole());
1465  return context->get(context_index);
1466  } else {
1467  // Object is not mapped, defer to the arguments.
1468  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1469  MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get(
1470  receiver, obj, key, arguments);
1471  Object* result;
1472  if (!maybe_result->ToObject(&result)) return maybe_result;
1473  // Elements of the arguments object in slow mode might be slow aliases.
1474  if (result->IsAliasedArgumentsEntry()) {
1476  Context* context = Context::cast(parameter_map->get(0));
1477  int context_index = entry->aliased_context_slot();
1478  ASSERT(!context->get(context_index)->IsTheHole());
1479  return context->get(context_index);
1480  } else {
1481  return result;
1482  }
1483  }
1484  }
1485 
1486  MUST_USE_RESULT static MaybeObject* SetLengthImpl(
1487  JSObject* obj,
1488  Object* length,
1489  FixedArray* parameter_map) {
1490  // TODO(mstarzinger): This was never implemented but will be used once we
1491  // correctly implement [[DefineOwnProperty]] on arrays.
1492  UNIMPLEMENTED();
1493  return obj;
1494  }
1495 
1496  MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1497  uint32_t key,
1498  JSReceiver::DeleteMode mode) {
1499  FixedArray* parameter_map = FixedArray::cast(obj->elements());
1500  Object* probe = GetParameterMapArg(obj, parameter_map, key);
1501  if (!probe->IsTheHole()) {
1502  // TODO(kmillikin): We could check if this was the last aliased
1503  // parameter, and revert to normal elements in that case. That
1504  // would enable GC of the context.
1505  parameter_map->set_the_hole(key + 2);
1506  } else {
1507  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1508  if (arguments->IsDictionary()) {
1509  return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
1510  } else {
1511  // It's difficult to access the version of DeleteCommon that is declared
1512  // in the templatized super class, call the concrete implementation in
1513  // the class for the most generalized ElementsKind subclass.
1514  return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode);
1515  }
1516  }
1517  return obj->GetHeap()->true_value();
1518  }
1519 
1521  uint32_t from_start,
1522  FixedArrayBase* to,
1523  ElementsKind to_kind,
1524  uint32_t to_start,
1525  int packed_size,
1526  int copy_size) {
1527  FixedArray* parameter_map = FixedArray::cast(from);
1528  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1529  ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
1530  return accessor->CopyElements(NULL, from_start, to, to_kind,
1531  to_start, copy_size, arguments);
1532  }
1533 
1534  static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
1535  FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
1536  return Max(static_cast<uint32_t>(parameter_map->length() - 2),
1537  ForArray(arguments)->GetCapacity(arguments));
1538  }
1539 
1540  static uint32_t GetKeyForIndexImpl(FixedArray* dict,
1541  uint32_t index) {
1542  return index;
1543  }
1544 
1545  static bool HasElementImpl(Object* receiver,
1546  JSObject* holder,
1547  uint32_t key,
1548  FixedArray* parameter_map) {
1549  Object* probe = GetParameterMapArg(holder, parameter_map, key);
1550  if (!probe->IsTheHole()) {
1551  return true;
1552  } else {
1553  FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
1554  ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
1555  return !accessor->Get(receiver, holder, key, arguments)->IsTheHole();
1556  }
1557  }
1558 
1559  private:
1560  static Object* GetParameterMapArg(JSObject* holder,
1561  FixedArray* parameter_map,
1562  uint32_t key) {
1563  uint32_t length = holder->IsJSArray()
1564  ? Smi::cast(JSArray::cast(holder)->length())->value()
1565  : parameter_map->length();
1566  return key < (length - 2 )
1567  ? parameter_map->get(key + 2)
1568  : parameter_map->GetHeap()->the_hole_value();
1569  }
1570 };
1571 
1572 
1574  switch (array->map()->instance_type()) {
1575  case FIXED_ARRAY_TYPE:
1576  if (array->IsDictionary()) {
1577  return elements_accessors_[DICTIONARY_ELEMENTS];
1578  } else {
1579  return elements_accessors_[FAST_HOLEY_ELEMENTS];
1580  }
1582  return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
1584  return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
1586  return elements_accessors_[EXTERNAL_SHORT_ELEMENTS];
1588  return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
1590  return elements_accessors_[EXTERNAL_INT_ELEMENTS];
1592  return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS];
1594  return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS];
1596  return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS];
1598  return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS];
1599  default:
1600  UNREACHABLE();
1601  return NULL;
1602  }
1603 }
1604 
1605 
1607  static ElementsAccessor* accessor_array[] = {
1608 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
1610 #undef ACCESSOR_ARRAY
1611  };
1612 
1613  STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
1615 
1616  elements_accessors_ = accessor_array;
1617 }
1618 
1619 
1621 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
1623 #undef ACCESSOR_DELETE
1624  elements_accessors_ = NULL;
1625 }
1626 
1627 
1628 template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
1629 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
1631  SetLengthImpl(JSObject* obj,
1632  Object* length,
1633  typename ElementsKindTraits::BackingStore* backing_store) {
1634  JSArray* array = JSArray::cast(obj);
1635 
1636  // Fast case: The new length fits into a Smi.
1637  MaybeObject* maybe_smi_length = length->ToSmi();
1638  Object* smi_length = Smi::FromInt(0);
1639  if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
1640  const int value = Smi::cast(smi_length)->value();
1641  if (value >= 0) {
1642  Object* new_length;
1643  MaybeObject* result = ElementsAccessorSubclass::
1644  SetLengthWithoutNormalize(backing_store, array, smi_length, value);
1645  if (!result->ToObject(&new_length)) return result;
1646  ASSERT(new_length->IsSmi() || new_length->IsUndefined());
1647  if (new_length->IsSmi()) {
1648  array->set_length(Smi::cast(new_length));
1649  return array;
1650  }
1651  } else {
1652  return ThrowArrayLengthRangeError(array->GetHeap());
1653  }
1654  }
1655 
1656  // Slow case: The new length does not fit into a Smi or conversion
1657  // to slow elements is needed for other reasons.
1658  if (length->IsNumber()) {
1659  uint32_t value;
1660  if (length->ToArrayIndex(&value)) {
1661  SeededNumberDictionary* dictionary;
1662  MaybeObject* maybe_object = array->NormalizeElements();
1663  if (!maybe_object->To(&dictionary)) return maybe_object;
1664  Object* new_length;
1665  MaybeObject* result = DictionaryElementsAccessor::
1666  SetLengthWithoutNormalize(dictionary, array, length, value);
1667  if (!result->ToObject(&new_length)) return result;
1668  ASSERT(new_length->IsNumber());
1669  array->set_length(new_length);
1670  return array;
1671  } else {
1672  return ThrowArrayLengthRangeError(array->GetHeap());
1673  }
1674  }
1675 
1676  // Fall-back case: The new length is not a number so make the array
1677  // size one and set only element to length.
1678  FixedArray* new_backing_store;
1679  MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1);
1680  if (!maybe_obj->To(&new_backing_store)) return maybe_obj;
1681  new_backing_store->set(0, length);
1682  { MaybeObject* result = array->SetContent(new_backing_store);
1683  if (result->IsFailure()) return result;
1684  }
1685  return array;
1686 }
1687 
1688 
1689 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
bool FLAG_enable_slow_asserts
static MUST_USE_RESULT MaybeObject * SetLengthImpl(JSObject *obj, Object *length, BackingStore *backing_store)
Definition: elements.cc:1139
Object * KeyAt(int entry)
Definition: objects.h:2841
static MUST_USE_RESULT MaybeObject * GetImpl(Object *receiver, JSObject *obj, uint32_t key, BackingStore *backing_store)
Definition: elements.cc:1129
FastDoubleElementsAccessor(const char *name)
Definition: elements.cc:1041
#define ACCESSOR_DELETE(Class, Kind, Store)
#define ACCESSOR_ARRAY(Class, Kind, Store)
MUST_USE_RESULT MaybeObject * AllocateFixedArray(int length, PretenureFlag pretenure)
Definition: heap.cc:4819
static MUST_USE_RESULT MaybeObject * GetImpl(Object *receiver, JSObject *obj, uint32_t key, FixedArray *parameter_map)
Definition: elements.cc:1456
void set(int index, Object *value)
Definition: objects-inl.h:1757
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:1496
bool InNewSpace(Object *object)
Definition: heap-inl.h:288
static String * cast(Object *obj)
static uint32_t GetCapacityImpl(FixedArray *parameter_map)
Definition: elements.cc:1534
virtual MUST_USE_RESULT MaybeObject * AddElementsToFixedArray(Object *receiver, JSObject *holder, FixedArray *to, FixedArrayBase *from)
Definition: elements.cc:641
static bool HasElementImpl(Object *receiver, JSObject *holder, uint32_t key, SeededNumberDictionary *backing_store)
Definition: elements.cc:1427
ElementsTraitsParam::BackingStore BackingStore
Definition: elements.cc:491
void set_length(Smi *length)
Definition: objects-inl.h:5278
static Smi * FromInt(int value)
Definition: objects-inl.h:981
bool IsFastObjectElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * ToSmi()
Definition: objects-inl.h:823
virtual MUST_USE_RESULT MaybeObject * SetCapacityAndLength(JSArray *array, int capacity, int length)
Definition: elements.cc:578
static bool HasElementImpl(Object *receiver, JSObject *holder, uint32_t key, BackingStore *backing_store)
Definition: elements.cc:1155
T Max(T a, T b)
Definition: utils.h:222
static bool HasElementImpl(Object *receiver, JSObject *holder, uint32_t key, BackingStore *backing_store)
Definition: elements.cc:527
static MUST_USE_RESULT MaybeObject * SetLengthImpl(JSObject *obj, Object *length, BackingStore *backing_store)
Definition: elements.cc:1631
virtual void Validate(JSObject *holder)
Definition: elements.cc:523
ExternalElementsAccessor(const char *name)
Definition: elements.cc:1119
virtual MUST_USE_RESULT MaybeObject * SetLength(JSArray *array, Object *length)
Definition: elements.cc:567
static Failure * Exception()
Definition: objects-inl.h:1024
static MaybeObject * SetFastElementsCapacityAndLength(JSObject *obj, uint32_t capacity, uint32_t length)
Definition: elements.cc:1046
static AliasedArgumentsEntry * cast(Object *obj)
DictionaryElementsAccessor(const char *name)
Definition: elements.cc:1260
static Handle< Object > TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:10072
#define ASSERT(condition)
Definition: checks.h:270
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:1400
KindTraits::BackingStore BackingStore
Definition: elements.cc:763
static MUST_USE_RESULT MaybeObject * SetLengthWithoutNormalize(SeededNumberDictionary *dict, JSArray *array, Object *length_object, uint32_t length)
Definition: elements.cc:1266
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:1148
static Context * cast(Object *context)
Definition: contexts.h:212
#define ELEMENTS_LIST(V)
Definition: elements.cc:76
ElementsTraitsParam ElementsTraits
Definition: elements.cc:490
virtual bool HasElement(Object *receiver, JSObject *holder, uint32_t key, FixedArrayBase *backing_store)
Definition: elements.cc:536
FastElementsAccessor(const char *name)
Definition: elements.cc:756
static uint32_t GetKeyForIndexImpl(SeededNumberDictionary *dict, uint32_t index)
Definition: elements.cc:1435
Factory * factory()
Definition: isolate.h:992
bool IsFastElementsKind(ElementsKind kind)
MUST_USE_RESULT MaybeObject * EnsureWritableFastElements()
Definition: objects-inl.h:4881
void set_the_hole(int index)
Definition: objects-inl.h:1900
static Smi * cast(Object *object)
bool Equals(String *other)
Definition: objects-inl.h:2419
static MUST_USE_RESULT MaybeObject * DeleteCommon(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:1322
static MUST_USE_RESULT MaybeObject * CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1367
static const int kCopyToEnd
Definition: elements.h:99
static uint32_t GetKeyForIndexImpl(FixedArray *dict, uint32_t index)
Definition: elements.cc:1540
Object * ValueAt(int entry)
Definition: objects.h:3067
void CopyWords(T *dst, T *src, int num_words)
Definition: v8utils.h:127
#define UNREACHABLE()
Definition: checks.h:50
virtual ElementsKind kind() const
Definition: elements.cc:493
static void ValidateImpl(JSObject *holder)
Definition: elements.cc:498
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:3236
MUST_USE_RESULT MaybeObject * SetContent(FixedArrayBase *storage)
Definition: objects-inl.h:5291
#define MUST_USE_RESULT
Definition: globals.h:346
bool IsFastPackedElementsKind(ElementsKind kind)
const int kDoubleSize
Definition: globals.h:218
static void ValidateContents(JSObject *holder, int length)
Definition: elements.cc:900
static MUST_USE_RESULT MaybeObject * SetFastElementsCapacityAndLength(JSObject *obj, int capacity, int length)
Definition: elements.cc:588
virtual MUST_USE_RESULT MaybeObject * Get(Object *receiver, JSObject *holder, uint32_t key, FixedArrayBase *backing_store)
Definition: elements.cc:547
static MaybeObject * DeleteCommon(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:826
int FastD2IChecked(double x)
Definition: conversions.h:58
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:1682
MUST_USE_RESULT MaybeObject * ResetElements()
Definition: objects-inl.h:1402
ElementsKind GetElementsKind()
Definition: objects-inl.h:4776
const int kPointerSize
Definition: globals.h:220
static uint32_t GetKeyForIndexImpl(BackingStore *backing_store, uint32_t index)
Definition: elements.cc:733
static MaybeObject * CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1054
static bool HasElementImpl(Object *receiver, JSObject *holder, uint32_t key, FixedArray *parameter_map)
Definition: elements.cc:1545
static void InitializeOncePerProcess()
Definition: elements.cc:1606
static MUST_USE_RESULT MaybeObject * GetImpl(Object *receiver, JSObject *obj, uint32_t key, BackingStore *backing_store)
Definition: elements.cc:558
static FixedDoubleArray * cast(Object *obj)
#define ELEMENTS_TRAITS(Class, KindParam, Store)
Definition: elements.cc:114
bool IsFastSmiElementsKind(ElementsKind kind)
static MUST_USE_RESULT MaybeObject * CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:600
MUST_USE_RESULT MaybeObject * SetFastElementsCapacityAndLength(int capacity, int length, SetFastElementsCapacitySmiMode smi_mode)
Definition: objects.cc:8789
static ElementsAccessor * ForArray(FixedArrayBase *array)
Definition: elements.cc:1573
WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation &)
Definition: objects-inl.h:1831
MUST_USE_RESULT MaybeObject * Shrink(Key key)
Definition: objects.cc:12523
virtual MUST_USE_RESULT MaybeObject * Get(Object *receiver, JSObject *holder, uint32_t key, FixedArrayBase *backing_store=NULL)=0
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:945
virtual MUST_USE_RESULT MaybeObject * CopyElements(JSObject *from_holder, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int copy_size, FixedArrayBase *from)
Definition: elements.cc:611
static int OffsetOfElementAt(int index)
Definition: objects.h:2356
static JSArray * cast(Object *obj)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
void RecordWrites(Address address, int start, int len)
Definition: heap-inl.h:336
const int kElementsKindCount
Definition: elements-kind.h:76
static const int kHeaderSize
Definition: objects.h:2296
MUST_USE_RESULT MaybeObject * SetFastDoubleElementsCapacityAndLength(int capacity, int length)
Definition: objects.cc:8855
void CopyObjectToObjectElements(FixedArray *from, ElementsKind from_kind, uint32_t from_start, FixedArray *to, ElementsKind to_kind, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:149
bool ShouldConvertToSlowElements(int new_capacity)
Definition: objects.cc:10308
static const int kCopyToEndAndInitializeToHole
Definition: elements.h:104
ElementsKindTraits< Kind >::BackingStore BackingStore
Definition: elements.cc:1124
static MaybeObject * SetLengthWithoutNormalize(BackingStore *backing_store, JSArray *array, Object *length_object, uint32_t length)
Definition: elements.cc:767
MUST_USE_RESULT MaybeObject * NumberFromUint32(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:240
IncrementalMarking * incremental_marking()
Definition: heap.h:1553
static MUST_USE_RESULT MaybeObject * SetLengthImpl(JSObject *obj, Object *length, FixedArray *parameter_map)
Definition: elements.cc:1486
#define UNIMPLEMENTED()
Definition: checks.h:48
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3077
Object * DeleteProperty(int entry, JSObject::DeleteMode mode)
Definition: objects.cc:12508
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:630
static Handle< SeededNumberDictionary > NormalizeElements(Handle< JSObject > object)
Definition: objects.cc:3408
#define HEAP
Definition: isolate.h:1433
InstanceType instance_type()
Definition: objects-inl.h:3009
static FixedArray * cast(Object *obj)
static bool HasElementImpl(Object *receiver, JSObject *holder, uint32_t key, typename KindTraits::BackingStore *backing_store)
Definition: elements.cc:889
static MUST_USE_RESULT MaybeObject * CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1520
void SetEntry(int entry, Object *key, Object *value)
Definition: objects-inl.h:5143
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
Object * get(int index)
Definition: objects-inl.h:1737
bool IsFastHoleyElementsKind(ElementsKind kind)
bool HasFastArgumentsElements()
Definition: objects.cc:9468
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3558
static MaybeObject * SetFastElementsCapacityAndLength(JSObject *obj, uint32_t capacity, uint32_t length)
Definition: elements.cc:972
virtual uint32_t GetCapacity(FixedArrayBase *backing_store)
Definition: elements.cc:728
PixelElementsAccessor(const char *name)
Definition: elements.cc:1250
Definition: objects.h:6953
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:117
virtual MUST_USE_RESULT MaybeObject * Delete(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)=0
int aliased_context_slot()
virtual uint32_t GetCapacity(FixedArrayBase *backing_store)=0
virtual uint32_t GetKeyForIndex(FixedArrayBase *backing_store, uint32_t index)
Definition: elements.cc:738
T Min(T a, T b)
Definition: utils.h:229
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1806
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:1731
ElementsAccessorBase(const char *name)
Definition: elements.cc:487
static uint32_t GetCapacityImpl(BackingStore *backing_store)
Definition: elements.cc:724
virtual MaybeObject * Delete(JSObject *obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:883
Handle< Object > NewNumberFromUint(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:613
static void ValidateContents(JSObject *holder, int length)
Definition: elements.cc:495
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
const char * name() const
Definition: elements.h:47
void ElementsRemoved(int n)
Definition: objects.h:2825
static MUST_USE_RESULT MaybeObject * GetImpl(Object *receiver, JSObject *obj, uint32_t key, SeededNumberDictionary *backing_store)
Definition: elements.cc:1406
bool IsFastDoubleElementsKind(ElementsKind kind)
static MaybeObject * CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind to_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:936