V8 Project
elements.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/arguments.h"
8 #include "src/conversions.h"
9 #include "src/elements.h"
10 #include "src/objects.h"
11 #include "src/utils.h"
12 
13 // Each concrete ElementsAccessor can handle exactly one ElementsKind,
14 // several abstract ElementsAccessor classes are used to allow sharing
15 // common code.
16 //
17 // Inheritance hierarchy:
18 // - ElementsAccessorBase (abstract)
19 // - FastElementsAccessor (abstract)
20 // - FastSmiOrObjectElementsAccessor
21 // - FastPackedSmiElementsAccessor
22 // - FastHoleySmiElementsAccessor
23 // - FastPackedObjectElementsAccessor
24 // - FastHoleyObjectElementsAccessor
25 // - FastDoubleElementsAccessor
26 // - FastPackedDoubleElementsAccessor
27 // - FastHoleyDoubleElementsAccessor
28 // - TypedElementsAccessor: template, with instantiations:
29 // - ExternalInt8ElementsAccessor
30 // - ExternalUint8ElementsAccessor
31 // - ExternalInt16ElementsAccessor
32 // - ExternalUint16ElementsAccessor
33 // - ExternalInt32ElementsAccessor
34 // - ExternalUint32ElementsAccessor
35 // - ExternalFloat32ElementsAccessor
36 // - ExternalFloat64ElementsAccessor
37 // - ExternalUint8ClampedElementsAccessor
38 // - FixedUint8ElementsAccessor
39 // - FixedInt8ElementsAccessor
40 // - FixedUint16ElementsAccessor
41 // - FixedInt16ElementsAccessor
42 // - FixedUint32ElementsAccessor
43 // - FixedInt32ElementsAccessor
44 // - FixedFloat32ElementsAccessor
45 // - FixedFloat64ElementsAccessor
46 // - FixedUint8ClampedElementsAccessor
47 // - DictionaryElementsAccessor
48 // - SloppyArgumentsElementsAccessor
49 
50 
51 namespace v8 {
52 namespace internal {
53 
54 
55 static const int kPackedSizeNotKnown = -1;
56 
57 
58 // First argument in list is the accessor class, the second argument is the
59 // accessor ElementsKind, and the third is the backing store class. Use the
60 // fast element handler for smi-only arrays. The implementation is currently
61 // identical. Note that the order must match that of the ElementsKind enum for
62 // the |accessor_array[]| below to work.
63 #define ELEMENTS_LIST(V) \
64  V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
65  V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \
66  FixedArray) \
67  V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
68  V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
69  V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \
70  FixedDoubleArray) \
71  V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
72  FixedDoubleArray) \
73  V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
74  SeededNumberDictionary) \
75  V(SloppyArgumentsElementsAccessor, SLOPPY_ARGUMENTS_ELEMENTS, \
76  FixedArray) \
77  V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, \
78  ExternalInt8Array) \
79  V(ExternalUint8ElementsAccessor, \
80  EXTERNAL_UINT8_ELEMENTS, ExternalUint8Array) \
81  V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \
82  ExternalInt16Array) \
83  V(ExternalUint16ElementsAccessor, \
84  EXTERNAL_UINT16_ELEMENTS, ExternalUint16Array) \
85  V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \
86  ExternalInt32Array) \
87  V(ExternalUint32ElementsAccessor, \
88  EXTERNAL_UINT32_ELEMENTS, ExternalUint32Array) \
89  V(ExternalFloat32ElementsAccessor, \
90  EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array) \
91  V(ExternalFloat64ElementsAccessor, \
92  EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array) \
93  V(ExternalUint8ClampedElementsAccessor, \
94  EXTERNAL_UINT8_CLAMPED_ELEMENTS, \
95  ExternalUint8ClampedArray) \
96  V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
97  V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
98  V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
99  V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
100  V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
101  V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
102  V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
103  V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
104  V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
105  FixedUint8ClampedArray)
106 
107 
108 template<ElementsKind Kind> class ElementsKindTraits {
109  public:
111 };
112 
113 #define ELEMENTS_TRAITS(Class, KindParam, Store) \
114 template<> class ElementsKindTraits<KindParam> { \
115  public: /* NOLINT */ \
116  static const ElementsKind Kind = KindParam; \
117  typedef Store BackingStore; \
118 };
120 #undef ELEMENTS_TRAITS
121 
122 
123 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL;
124 
125 
126 static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) {
128  Object* key = *key_handle;
129  int len0 = array->length();
130  for (int i = 0; i < len0; i++) {
131  Object* element = array->get(i);
132  if (element->IsSmi() && element == key) return true;
133  if (element->IsString() &&
134  key->IsString() && String::cast(element)->Equals(String::cast(key))) {
135  return true;
136  }
137  }
138  return false;
139 }
140 
141 
144  THROW_NEW_ERROR(isolate, NewRangeError("invalid_array_length",
145  HandleVector<Object>(NULL, 0)),
146  Object);
147 }
148 
149 
151  ElementsKind from_kind,
152  uint32_t from_start,
153  FixedArrayBase* to_base,
154  ElementsKind to_kind, uint32_t to_start,
155  int raw_copy_size) {
156  DCHECK(to_base->map() !=
157  from_base->GetIsolate()->heap()->fixed_cow_array_map());
158  DisallowHeapAllocation no_allocation;
159  int copy_size = raw_copy_size;
160  if (raw_copy_size < 0) {
161  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
163  copy_size = Min(from_base->length() - from_start,
164  to_base->length() - to_start);
166  int start = to_start + copy_size;
167  int length = to_base->length() - start;
168  if (length > 0) {
169  Heap* heap = from_base->GetHeap();
170  MemsetPointer(FixedArray::cast(to_base)->data_start() + start,
171  heap->the_hole_value(), length);
172  }
173  }
174  }
175  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
176  (copy_size + static_cast<int>(from_start)) <= from_base->length());
177  if (copy_size == 0) return;
178  FixedArray* from = FixedArray::cast(from_base);
179  FixedArray* to = FixedArray::cast(to_base);
182  Address to_address = to->address() + FixedArray::kHeaderSize;
183  Address from_address = from->address() + FixedArray::kHeaderSize;
184  CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
185  reinterpret_cast<Object**>(from_address) + from_start,
186  static_cast<size_t>(copy_size));
187  if (IsFastObjectElementsKind(from_kind) &&
188  IsFastObjectElementsKind(to_kind)) {
189  Heap* heap = from->GetHeap();
190  if (!heap->InNewSpace(to)) {
191  heap->RecordWrites(to->address(),
192  to->OffsetOfElementAt(to_start),
193  copy_size);
194  }
196  }
197 }
198 
199 
201  FixedArrayBase* from_base, uint32_t from_start, FixedArrayBase* to_base,
202  ElementsKind to_kind, uint32_t to_start, int raw_copy_size) {
203  DisallowHeapAllocation no_allocation;
204  SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base);
205  int copy_size = raw_copy_size;
206  Heap* heap = from->GetHeap();
207  if (raw_copy_size < 0) {
208  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
210  copy_size = from->max_number_key() + 1 - from_start;
212  int start = to_start + copy_size;
213  int length = to_base->length() - start;
214  if (length > 0) {
215  Heap* heap = from->GetHeap();
216  MemsetPointer(FixedArray::cast(to_base)->data_start() + start,
217  heap->the_hole_value(), length);
218  }
219  }
220  }
221  DCHECK(to_base != from_base);
223  if (copy_size == 0) return;
224  FixedArray* to = FixedArray::cast(to_base);
225  uint32_t to_length = to->length();
226  if (to_start + copy_size > to_length) {
227  copy_size = to_length - to_start;
228  }
229  for (int i = 0; i < copy_size; i++) {
230  int entry = from->FindEntry(i + from_start);
231  if (entry != SeededNumberDictionary::kNotFound) {
232  Object* value = from->ValueAt(entry);
233  DCHECK(!value->IsTheHole());
234  to->set(i + to_start, value, SKIP_WRITE_BARRIER);
235  } else {
236  to->set_the_hole(i + to_start);
237  }
238  }
239  if (IsFastObjectElementsKind(to_kind)) {
240  if (!heap->InNewSpace(to)) {
241  heap->RecordWrites(to->address(),
242  to->OffsetOfElementAt(to_start),
243  copy_size);
244  }
246  }
247 }
248 
249 
250 // NOTE: this method violates the handlified function signature convention:
251 // raw pointer parameters in the function that allocates.
252 // See ElementsAccessorBase::CopyElements() for details.
254  uint32_t from_start,
255  FixedArrayBase* to_base,
256  ElementsKind to_kind, uint32_t to_start,
257  int raw_copy_size) {
259  int copy_size = raw_copy_size;
260  if (raw_copy_size < 0) {
261  DisallowHeapAllocation no_allocation;
262  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
264  copy_size = Min(from_base->length() - from_start,
265  to_base->length() - to_start);
267  // Also initialize the area that will be copied over since HeapNumber
268  // allocation below can cause an incremental marking step, requiring all
269  // existing heap objects to be propertly initialized.
270  int start = to_start;
271  int length = to_base->length() - start;
272  if (length > 0) {
273  Heap* heap = from_base->GetHeap();
274  MemsetPointer(FixedArray::cast(to_base)->data_start() + start,
275  heap->the_hole_value(), length);
276  }
277  }
278  }
279  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
280  (copy_size + static_cast<int>(from_start)) <= from_base->length());
281  if (copy_size == 0) return;
282 
283  // From here on, the code below could actually allocate. Therefore the raw
284  // values are wrapped into handles.
285  Isolate* isolate = from_base->GetIsolate();
286  Handle<FixedDoubleArray> from(FixedDoubleArray::cast(from_base), isolate);
287  Handle<FixedArray> to(FixedArray::cast(to_base), isolate);
288  for (int i = 0; i < copy_size; ++i) {
289  HandleScope scope(isolate);
290  if (IsFastSmiElementsKind(to_kind)) {
291  UNIMPLEMENTED();
292  } else {
294  Handle<Object> value = FixedDoubleArray::get(from, i + from_start);
295  to->set(i + to_start, *value, UPDATE_WRITE_BARRIER);
296  }
297  }
298 }
299 
300 
302  uint32_t from_start,
303  FixedArrayBase* to_base,
304  uint32_t to_start, int raw_copy_size) {
305  DisallowHeapAllocation no_allocation;
306  int copy_size = raw_copy_size;
307  if (raw_copy_size < 0) {
308  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
310  copy_size = Min(from_base->length() - from_start,
311  to_base->length() - to_start);
313  for (int i = to_start + copy_size; i < to_base->length(); ++i) {
314  FixedDoubleArray::cast(to_base)->set_the_hole(i);
315  }
316  }
317  }
318  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
319  (copy_size + static_cast<int>(from_start)) <= from_base->length());
320  if (copy_size == 0) return;
321  FixedDoubleArray* from = FixedDoubleArray::cast(from_base);
322  FixedDoubleArray* to = FixedDoubleArray::cast(to_base);
323  Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
324  Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
325  to_address += kDoubleSize * to_start;
326  from_address += kDoubleSize * from_start;
327  int words_per_double = (kDoubleSize / kPointerSize);
328  CopyWords(reinterpret_cast<Object**>(to_address),
329  reinterpret_cast<Object**>(from_address),
330  static_cast<size_t>(words_per_double * copy_size));
331 }
332 
333 
335  uint32_t from_start,
336  FixedArrayBase* to_base, uint32_t to_start,
337  int raw_copy_size) {
338  DisallowHeapAllocation no_allocation;
339  int copy_size = raw_copy_size;
340  if (raw_copy_size < 0) {
341  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
343  copy_size = from_base->length() - from_start;
345  for (int i = to_start + copy_size; i < to_base->length(); ++i) {
346  FixedDoubleArray::cast(to_base)->set_the_hole(i);
347  }
348  }
349  }
350  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
351  (copy_size + static_cast<int>(from_start)) <= from_base->length());
352  if (copy_size == 0) return;
353  FixedArray* from = FixedArray::cast(from_base);
354  FixedDoubleArray* to = FixedDoubleArray::cast(to_base);
355  Object* the_hole = from->GetHeap()->the_hole_value();
356  for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size);
357  from_start < from_end; from_start++, to_start++) {
358  Object* hole_or_smi = from->get(from_start);
359  if (hole_or_smi == the_hole) {
360  to->set_the_hole(to_start);
361  } else {
362  to->set(to_start, Smi::cast(hole_or_smi)->value());
363  }
364  }
365 }
366 
367 
369  uint32_t from_start,
370  FixedArrayBase* to_base,
371  uint32_t to_start, int packed_size,
372  int raw_copy_size) {
373  DisallowHeapAllocation no_allocation;
374  int copy_size = raw_copy_size;
375  uint32_t to_end;
376  if (raw_copy_size < 0) {
377  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
379  copy_size = packed_size - from_start;
381  to_end = to_base->length();
382  for (uint32_t i = to_start + copy_size; i < to_end; ++i) {
383  FixedDoubleArray::cast(to_base)->set_the_hole(i);
384  }
385  } else {
386  to_end = to_start + static_cast<uint32_t>(copy_size);
387  }
388  } else {
389  to_end = to_start + static_cast<uint32_t>(copy_size);
390  }
391  DCHECK(static_cast<int>(to_end) <= to_base->length());
392  DCHECK(packed_size >= 0 && packed_size <= copy_size);
393  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
394  (copy_size + static_cast<int>(from_start)) <= from_base->length());
395  if (copy_size == 0) return;
396  FixedArray* from = FixedArray::cast(from_base);
397  FixedDoubleArray* to = FixedDoubleArray::cast(to_base);
398  for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
399  from_start < from_end; from_start++, to_start++) {
400  Object* smi = from->get(from_start);
401  DCHECK(!smi->IsTheHole());
402  to->set(to_start, Smi::cast(smi)->value());
403  }
404 }
405 
406 
408  uint32_t from_start,
409  FixedArrayBase* to_base,
410  uint32_t to_start, int raw_copy_size) {
411  DisallowHeapAllocation no_allocation;
412  int copy_size = raw_copy_size;
413  if (raw_copy_size < 0) {
414  DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
416  copy_size = from_base->length() - from_start;
418  for (int i = to_start + copy_size; i < to_base->length(); ++i) {
419  FixedDoubleArray::cast(to_base)->set_the_hole(i);
420  }
421  }
422  }
423  DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
424  (copy_size + static_cast<int>(from_start)) <= from_base->length());
425  if (copy_size == 0) return;
426  FixedArray* from = FixedArray::cast(from_base);
427  FixedDoubleArray* to = FixedDoubleArray::cast(to_base);
428  Object* the_hole = from->GetHeap()->the_hole_value();
429  for (uint32_t from_end = from_start + copy_size;
430  from_start < from_end; from_start++, to_start++) {
431  Object* hole_or_object = from->get(from_start);
432  if (hole_or_object == the_hole) {
433  to->set_the_hole(to_start);
434  } else {
435  to->set(to_start, hole_or_object->Number());
436  }
437  }
438 }
439 
440 
442  uint32_t from_start,
443  FixedArrayBase* to_base,
444  uint32_t to_start,
445  int raw_copy_size) {
446  DisallowHeapAllocation no_allocation;
447  SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base);
448  int copy_size = raw_copy_size;
449  if (copy_size < 0) {
450  DCHECK(copy_size == ElementsAccessor::kCopyToEnd ||
452  copy_size = from->max_number_key() + 1 - from_start;
454  for (int i = to_start + copy_size; i < to_base->length(); ++i) {
455  FixedDoubleArray::cast(to_base)->set_the_hole(i);
456  }
457  }
458  }
459  if (copy_size == 0) return;
460  FixedDoubleArray* to = FixedDoubleArray::cast(to_base);
461  uint32_t to_length = to->length();
462  if (to_start + copy_size > to_length) {
463  copy_size = to_length - to_start;
464  }
465  for (int i = 0; i < copy_size; i++) {
466  int entry = from->FindEntry(i + from_start);
467  if (entry != SeededNumberDictionary::kNotFound) {
468  to->set(i + to_start, from->ValueAt(entry)->Number());
469  } else {
470  to->set_the_hole(i + to_start);
471  }
472  }
473 }
474 
475 
476 static void TraceTopFrame(Isolate* isolate) {
477  StackFrameIterator it(isolate);
478  if (it.done()) {
479  PrintF("unknown location (no JavaScript frames present)");
480  return;
481  }
482  StackFrame* raw_frame = it.frame();
483  if (raw_frame->is_internal()) {
484  Code* apply_builtin = isolate->builtins()->builtin(
485  Builtins::kFunctionApply);
486  if (raw_frame->unchecked_code() == apply_builtin) {
487  PrintF("apply from ");
488  it.Advance();
489  raw_frame = it.frame();
490  }
491  }
492  JavaScriptFrame::PrintTop(isolate, stdout, false, true);
493 }
494 
495 
496 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key,
497  bool allow_appending) {
498  DisallowHeapAllocation no_allocation;
499  Object* raw_length = NULL;
500  const char* elements_type = "array";
501  if (obj->IsJSArray()) {
502  JSArray* array = JSArray::cast(*obj);
503  raw_length = array->length();
504  } else {
505  raw_length = Smi::FromInt(obj->elements()->length());
506  elements_type = "object";
507  }
508 
509  if (raw_length->IsNumber()) {
510  double n = raw_length->Number();
511  if (FastI2D(FastD2UI(n)) == n) {
512  int32_t int32_length = DoubleToInt32(n);
513  uint32_t compare_length = static_cast<uint32_t>(int32_length);
514  if (allow_appending) compare_length++;
515  if (key >= compare_length) {
516  PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ",
517  elements_type, op, elements_type,
518  static_cast<int>(int32_length),
519  static_cast<int>(key));
520  TraceTopFrame(obj->GetIsolate());
521  PrintF("]\n");
522  }
523  } else {
524  PrintF("[%s elements length not integer value in ", elements_type);
525  TraceTopFrame(obj->GetIsolate());
526  PrintF("]\n");
527  }
528  } else {
529  PrintF("[%s elements length not a number in ", elements_type);
530  TraceTopFrame(obj->GetIsolate());
531  PrintF("]\n");
532  }
533 }
534 
535 
536 // Base class for element handler implementations. Contains the
537 // the common logic for objects with different ElementsKinds.
538 // Subclasses must specialize method for which the element
539 // implementation differs from the base class implementation.
540 //
541 // This class is intended to be used in the following way:
542 //
543 // class SomeElementsAccessor :
544 // public ElementsAccessorBase<SomeElementsAccessor,
545 // BackingStoreClass> {
546 // ...
547 // }
548 //
549 // This is an example of the Curiously Recurring Template Pattern (see
550 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
551 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
552 // specialization of SomeElementsAccessor methods).
553 template <typename ElementsAccessorSubclass,
554  typename ElementsTraitsParam>
556  protected:
557  explicit ElementsAccessorBase(const char* name)
558  : ElementsAccessor(name) { }
559 
560  typedef ElementsTraitsParam ElementsTraits;
561  typedef typename ElementsTraitsParam::BackingStore BackingStore;
562 
563  virtual ElementsKind kind() const FINAL OVERRIDE {
564  return ElementsTraits::Kind;
565  }
566 
567  static void ValidateContents(Handle<JSObject> holder, int length) {
568  }
569 
570  static void ValidateImpl(Handle<JSObject> holder) {
571  Handle<FixedArrayBase> fixed_array_base(holder->elements());
572  if (!fixed_array_base->IsHeapObject()) return;
573  // Arrays that have been shifted in place can't be verified.
574  if (fixed_array_base->IsFiller()) return;
575  int length = 0;
576  if (holder->IsJSArray()) {
577  Object* length_obj = Handle<JSArray>::cast(holder)->length();
578  if (length_obj->IsSmi()) {
579  length = Smi::cast(length_obj)->value();
580  }
581  } else {
582  length = fixed_array_base->length();
583  }
584  ElementsAccessorSubclass::ValidateContents(holder, length);
585  }
586 
587  virtual void Validate(Handle<JSObject> holder) FINAL OVERRIDE {
589  ElementsAccessorSubclass::ValidateImpl(holder);
590  }
591 
592  static bool HasElementImpl(Handle<Object> receiver,
593  Handle<JSObject> holder,
594  uint32_t key,
595  Handle<FixedArrayBase> backing_store) {
596  return ElementsAccessorSubclass::GetAttributesImpl(
597  receiver, holder, key, backing_store) != ABSENT;
598  }
599 
600  virtual bool HasElement(
601  Handle<Object> receiver,
602  Handle<JSObject> holder,
603  uint32_t key,
604  Handle<FixedArrayBase> backing_store) FINAL OVERRIDE {
605  return ElementsAccessorSubclass::HasElementImpl(
606  receiver, holder, key, backing_store);
607  }
608 
610  Handle<Object> receiver,
611  Handle<JSObject> holder,
612  uint32_t key,
613  Handle<FixedArrayBase> backing_store) FINAL OVERRIDE {
614  if (!IsExternalArrayElementsKind(ElementsTraits::Kind) &&
615  FLAG_trace_js_array_abuse) {
616  CheckArrayAbuse(holder, "elements read", key);
617  }
618 
619  if (IsExternalArrayElementsKind(ElementsTraits::Kind) &&
620  FLAG_trace_external_array_abuse) {
621  CheckArrayAbuse(holder, "external elements read", key);
622  }
623 
624  return ElementsAccessorSubclass::GetImpl(
625  receiver, holder, key, backing_store);
626  }
627 
629  Handle<Object> receiver,
630  Handle<JSObject> obj,
631  uint32_t key,
632  Handle<FixedArrayBase> backing_store) {
633  if (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) {
634  return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
635  } else {
636  return backing_store->GetIsolate()->factory()->the_hole_value();
637  }
638  }
639 
641  Handle<Object> receiver,
642  Handle<JSObject> holder,
643  uint32_t key,
644  Handle<FixedArrayBase> backing_store) FINAL OVERRIDE {
645  return ElementsAccessorSubclass::GetAttributesImpl(
646  receiver, holder, key, backing_store);
647  }
648 
650  Handle<Object> receiver,
651  Handle<JSObject> obj,
652  uint32_t key,
653  Handle<FixedArrayBase> backing_store) {
654  if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) {
655  return ABSENT;
656  }
657  return
658  Handle<BackingStore>::cast(backing_store)->is_the_hole(key)
659  ? ABSENT : NONE;
660  }
661 
663  Handle<Object> receiver,
664  Handle<JSObject> holder,
665  uint32_t key,
666  Handle<FixedArrayBase> backing_store) FINAL OVERRIDE {
667  return ElementsAccessorSubclass::GetAccessorPairImpl(
668  receiver, holder, key, backing_store);
669  }
670 
672  Handle<Object> receiver,
673  Handle<JSObject> obj,
674  uint32_t key,
675  Handle<FixedArrayBase> backing_store) {
676  return MaybeHandle<AccessorPair>();
677  }
678 
680  Handle<JSArray> array,
681  Handle<Object> length) FINAL OVERRIDE {
682  return ElementsAccessorSubclass::SetLengthImpl(
683  array, length, handle(array->elements()));
684  }
685 
687  Handle<JSObject> obj,
688  Handle<Object> length,
689  Handle<FixedArrayBase> backing_store);
690 
691  virtual void SetCapacityAndLength(
692  Handle<JSArray> array,
693  int capacity,
694  int length) FINAL OVERRIDE {
695  ElementsAccessorSubclass::
696  SetFastElementsCapacityAndLength(array, capacity, length);
697  }
698 
700  Handle<JSObject> obj,
701  int capacity,
702  int length) {
703  UNIMPLEMENTED();
704  }
705 
707  Handle<JSObject> obj,
708  uint32_t key,
710 
711  static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
712  FixedArrayBase* to, ElementsKind from_kind,
713  uint32_t to_start, int packed_size,
714  int copy_size) {
715  UNREACHABLE();
716  }
717 
718  virtual void CopyElements(
720  uint32_t from_start,
721  ElementsKind from_kind,
723  uint32_t to_start,
724  int copy_size) FINAL OVERRIDE {
725  DCHECK(!from.is_null());
726  // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods
727  // violate the handlified function signature convention:
728  // raw pointer parameters in the function that allocates. This is done
729  // intentionally to avoid ArrayConcat() builtin performance degradation.
730  // See the comment in another ElementsAccessorBase::CopyElements() for
731  // details.
732  ElementsAccessorSubclass::CopyElementsImpl(*from, from_start, *to,
733  from_kind, to_start,
734  kPackedSizeNotKnown, copy_size);
735  }
736 
737  virtual void CopyElements(
738  JSObject* from_holder,
739  uint32_t from_start,
740  ElementsKind from_kind,
742  uint32_t to_start,
743  int copy_size) FINAL OVERRIDE {
744  int packed_size = kPackedSizeNotKnown;
745  bool is_packed = IsFastPackedElementsKind(from_kind) &&
746  from_holder->IsJSArray();
747  if (is_packed) {
748  packed_size =
749  Smi::cast(JSArray::cast(from_holder)->length())->value();
750  if (copy_size >= 0 && packed_size > copy_size) {
751  packed_size = copy_size;
752  }
753  }
754  FixedArrayBase* from = from_holder->elements();
755  // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods
756  // violate the handlified function signature convention:
757  // raw pointer parameters in the function that allocates. This is done
758  // intentionally to avoid ArrayConcat() builtin performance degradation.
759  //
760  // Details: The idea is that allocations actually happen only in case of
761  // copying from object with fast double elements to object with object
762  // elements. In all the other cases there are no allocations performed and
763  // handle creation causes noticeable performance degradation of the builtin.
764  ElementsAccessorSubclass::CopyElementsImpl(
765  from, from_start, *to, from_kind, to_start, packed_size, copy_size);
766  }
767 
769  Handle<Object> receiver,
770  Handle<JSObject> holder,
773  int len0 = to->length();
774 #ifdef ENABLE_SLOW_DCHECKS
776  for (int i = 0; i < len0; i++) {
777  DCHECK(!to->get(i)->IsTheHole());
778  }
779  }
780 #endif
781 
782  // Optimize if 'other' is empty.
783  // We cannot optimize if 'this' is empty, as other may have holes.
784  uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(from);
785  if (len1 == 0) return to;
786 
787  Isolate* isolate = from->GetIsolate();
788 
789  // Compute how many elements are not in other.
790  uint32_t extra = 0;
791  for (uint32_t y = 0; y < len1; y++) {
792  uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
793  if (ElementsAccessorSubclass::HasElementImpl(
794  receiver, holder, key, from)) {
795  Handle<Object> value;
797  isolate, value,
798  ElementsAccessorSubclass::GetImpl(receiver, holder, key, from),
799  FixedArray);
800 
801  DCHECK(!value->IsTheHole());
802  if (!HasKey(to, value)) {
803  extra++;
804  }
805  }
806  }
807 
808  if (extra == 0) return to;
809 
810  // Allocate the result
811  Handle<FixedArray> result = isolate->factory()->NewFixedArray(len0 + extra);
812 
813  // Fill in the content
814  {
816  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
817  for (int i = 0; i < len0; i++) {
818  Object* e = to->get(i);
819  DCHECK(e->IsString() || e->IsNumber());
820  result->set(i, e, mode);
821  }
822  }
823  // Fill in the extra values.
824  uint32_t index = 0;
825  for (uint32_t y = 0; y < len1; y++) {
826  uint32_t key =
827  ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
828  if (ElementsAccessorSubclass::HasElementImpl(
829  receiver, holder, key, from)) {
830  Handle<Object> value;
832  isolate, value,
833  ElementsAccessorSubclass::GetImpl(receiver, holder, key, from),
834  FixedArray);
835  if (!value->IsTheHole() && !HasKey(to, value)) {
836  result->set(len0 + index, *value);
837  index++;
838  }
839  }
840  }
841  DCHECK(extra == index);
842  return result;
843  }
844 
845  protected:
847  return backing_store->length();
848  }
849 
851  FINAL OVERRIDE {
852  return ElementsAccessorSubclass::GetCapacityImpl(backing_store);
853  }
854 
856  uint32_t index) {
857  return index;
858  }
859 
861  uint32_t index) FINAL OVERRIDE {
862  return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index);
863  }
864 
865  private:
867 };
868 
869 
870 // Super class for all fast element arrays.
871 template<typename FastElementsAccessorSubclass,
872  typename KindTraits>
874  : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
875  public:
876  explicit FastElementsAccessor(const char* name)
877  : ElementsAccessorBase<FastElementsAccessorSubclass,
878  KindTraits>(name) {}
879  protected:
880  friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
882 
883  typedef typename KindTraits::BackingStore BackingStore;
884 
885  // Adjusts the length of the fast backing store.
887  Handle<FixedArrayBase> backing_store,
888  Handle<JSArray> array,
889  Handle<Object> length_object,
890  uint32_t length) {
891  Isolate* isolate = array->GetIsolate();
892  uint32_t old_capacity = backing_store->length();
893  Handle<Object> old_length(array->length(), isolate);
894  bool same_or_smaller_size = old_length->IsSmi() &&
895  static_cast<uint32_t>(Handle<Smi>::cast(old_length)->value()) >= length;
896  ElementsKind kind = array->GetElementsKind();
897 
898  if (!same_or_smaller_size && IsFastElementsKind(kind) &&
902  }
903 
904  // Check whether the backing store should be shrunk.
905  if (length <= old_capacity) {
906  if (array->HasFastSmiOrObjectElements()) {
907  backing_store = JSObject::EnsureWritableFastElements(array);
908  }
909  if (2 * length <= old_capacity) {
910  // If more than half the elements won't be used, trim the array.
911  if (length == 0) {
912  array->initialize_elements();
913  } else {
915  *backing_store, old_capacity - length);
916  }
917  } else {
918  // Otherwise, fill the unused tail with holes.
919  int old_length = FastD2IChecked(array->length()->Number());
920  for (int i = length; i < old_length; i++) {
921  Handle<BackingStore>::cast(backing_store)->set_the_hole(i);
922  }
923  }
924  return length_object;
925  }
926 
927  // Check whether the backing store should be expanded.
929  uint32_t new_capacity = length > min ? length : min;
930  FastElementsAccessorSubclass::SetFastElementsCapacityAndLength(
931  array, new_capacity, length);
933  return length_object;
934  }
935 
937  uint32_t key,
939  DCHECK(obj->HasFastSmiOrObjectElements() ||
940  obj->HasFastDoubleElements() ||
941  obj->HasFastArgumentsElements());
942  Isolate* isolate = obj->GetIsolate();
943  Heap* heap = obj->GetHeap();
944  Handle<FixedArrayBase> elements(obj->elements());
945  if (*elements == heap->empty_fixed_array()) {
946  return isolate->factory()->true_value();
947  }
948  Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
949  bool is_sloppy_arguments_elements_map =
950  backing_store->map() == heap->sloppy_arguments_elements_map();
951  if (is_sloppy_arguments_elements_map) {
952  backing_store = handle(
953  BackingStore::cast(Handle<FixedArray>::cast(backing_store)->get(1)),
954  isolate);
955  }
956  uint32_t length = static_cast<uint32_t>(
957  obj->IsJSArray()
958  ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value()
959  : backing_store->length());
960  if (key < length) {
961  if (!is_sloppy_arguments_elements_map) {
962  ElementsKind kind = KindTraits::Kind;
965  }
966  if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
968  backing_store = Handle<BackingStore>::cast(writable);
969  }
970  }
971  backing_store->set_the_hole(key);
972  // If an old space backing store is larger than a certain size and
973  // has too few used values, normalize it.
974  // To avoid doing the check on every delete we require at least
975  // one adjacent hole to the value being deleted.
976  const int kMinLengthForSparsenessCheck = 64;
977  if (backing_store->length() >= kMinLengthForSparsenessCheck &&
978  !heap->InNewSpace(*backing_store) &&
979  ((key > 0 && backing_store->is_the_hole(key - 1)) ||
980  (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
981  int num_used = 0;
982  for (int i = 0; i < backing_store->length(); ++i) {
983  if (!backing_store->is_the_hole(i)) ++num_used;
984  // Bail out early if more than 1/4 is used.
985  if (4 * num_used > backing_store->length()) break;
986  }
987  if (4 * num_used <= backing_store->length()) {
989  }
990  }
991  }
992  return isolate->factory()->true_value();
993  }
994 
996  Handle<JSObject> obj,
997  uint32_t key,
999  return DeleteCommon(obj, key, mode);
1000  }
1001 
1002  static bool HasElementImpl(
1003  Handle<Object> receiver,
1004  Handle<JSObject> holder,
1005  uint32_t key,
1006  Handle<FixedArrayBase> backing_store) {
1007  if (key >= static_cast<uint32_t>(backing_store->length())) {
1008  return false;
1009  }
1010  return !Handle<BackingStore>::cast(backing_store)->is_the_hole(key);
1011  }
1012 
1013  static void ValidateContents(Handle<JSObject> holder, int length) {
1014 #if DEBUG
1015  Isolate* isolate = holder->GetIsolate();
1016  HandleScope scope(isolate);
1017  Handle<FixedArrayBase> elements(holder->elements(), isolate);
1018  Map* map = elements->map();
1019  DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
1020  (map == isolate->heap()->fixed_array_map() ||
1021  map == isolate->heap()->fixed_cow_array_map())) ||
1022  (IsFastDoubleElementsKind(KindTraits::Kind) ==
1023  ((map == isolate->heap()->fixed_array_map() && length == 0) ||
1024  map == isolate->heap()->fixed_double_array_map())));
1025  DisallowHeapAllocation no_gc;
1026  for (int i = 0; i < length; i++) {
1027  HandleScope scope(isolate);
1028  Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
1029  DCHECK((!IsFastSmiElementsKind(KindTraits::Kind) ||
1030  BackingStore::get(backing_store, i)->IsSmi()) ||
1031  (IsFastHoleyElementsKind(KindTraits::Kind) ==
1032  backing_store->is_the_hole(i)));
1033  }
1034 #endif
1035  }
1036 };
1037 
1038 
1040  switch (array->map()->instance_type()) {
1041  case FIXED_ARRAY_TYPE:
1042  if (array->IsDictionary()) {
1043  return DICTIONARY_ELEMENTS;
1044  } else {
1045  return FAST_HOLEY_ELEMENTS;
1046  }
1049 
1050 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1051  case EXTERNAL_##TYPE##_ARRAY_TYPE: \
1052  return EXTERNAL_##TYPE##_ELEMENTS; \
1053  case FIXED_##TYPE##_ARRAY_TYPE: \
1054  return TYPE##_ELEMENTS;
1055 
1057 #undef TYPED_ARRAY_CASE
1058 
1059  default:
1060  UNREACHABLE();
1061  }
1062  return FAST_HOLEY_ELEMENTS;
1063 }
1064 
1065 
1066 template<typename FastElementsAccessorSubclass,
1067  typename KindTraits>
1069  : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1070  public:
1072  : FastElementsAccessor<FastElementsAccessorSubclass,
1073  KindTraits>(name) {}
1074 
1075  // NOTE: this method violates the handlified function signature convention:
1076  // raw pointer parameters in the function that allocates.
1077  // See ElementsAccessor::CopyElements() for details.
1078  // This method could actually allocate if copying from double elements to
1079  // object elements.
1080  static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1081  FixedArrayBase* to, ElementsKind from_kind,
1082  uint32_t to_start, int packed_size,
1083  int copy_size) {
1084  DisallowHeapAllocation no_gc;
1085  ElementsKind to_kind = KindTraits::Kind;
1086  switch (from_kind) {
1087  case FAST_SMI_ELEMENTS:
1089  case FAST_ELEMENTS:
1090  case FAST_HOLEY_ELEMENTS:
1091  CopyObjectToObjectElements(from, from_kind, from_start, to, to_kind,
1092  to_start, copy_size);
1093  break;
1094  case FAST_DOUBLE_ELEMENTS:
1096  AllowHeapAllocation allow_allocation;
1098  from, from_start, to, to_kind, to_start, copy_size);
1099  break;
1100  }
1101  case DICTIONARY_ELEMENTS:
1102  CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
1103  copy_size);
1104  break;
1106  // TODO(verwaest): This is a temporary hack to support extending
1107  // SLOPPY_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength.
1108  // This case should be UNREACHABLE().
1109  FixedArray* parameter_map = FixedArray::cast(from);
1110  FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
1111  ElementsKind from_kind = ElementsKindForArray(arguments);
1112  CopyElementsImpl(arguments, from_start, to, from_kind,
1113  to_start, packed_size, copy_size);
1114  break;
1115  }
1116 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1117  case EXTERNAL_##TYPE##_ELEMENTS: \
1118  case TYPE##_ELEMENTS: \
1119  UNREACHABLE();
1121 #undef TYPED_ARRAY_CASE
1122  }
1123  }
1124 
1125 
1127  Handle<JSObject> obj,
1128  uint32_t capacity,
1129  uint32_t length) {
1130  JSObject::SetFastElementsCapacitySmiMode set_capacity_mode =
1131  obj->HasFastSmiElements()
1135  obj, capacity, length, set_capacity_mode);
1136  }
1137 };
1138 
1139 
1142  FastPackedSmiElementsAccessor,
1143  ElementsKindTraits<FAST_SMI_ELEMENTS> > {
1144  public:
1145  explicit FastPackedSmiElementsAccessor(const char* name)
1149 };
1150 
1151 
1154  FastHoleySmiElementsAccessor,
1155  ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > {
1156  public:
1157  explicit FastHoleySmiElementsAccessor(const char* name)
1161 };
1162 
1163 
1166  FastPackedObjectElementsAccessor,
1167  ElementsKindTraits<FAST_ELEMENTS> > {
1168  public:
1173 };
1174 
1175 
1178  FastHoleyObjectElementsAccessor,
1179  ElementsKindTraits<FAST_HOLEY_ELEMENTS> > {
1180  public:
1185 };
1186 
1187 
1188 template<typename FastElementsAccessorSubclass,
1189  typename KindTraits>
1191  : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1192  public:
1193  explicit FastDoubleElementsAccessor(const char* name)
1194  : FastElementsAccessor<FastElementsAccessorSubclass,
1195  KindTraits>(name) {}
1196 
1198  uint32_t capacity,
1199  uint32_t length) {
1200  JSObject::SetFastDoubleElementsCapacityAndLength(obj, capacity, length);
1201  }
1202 
1203  protected:
1204  static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1205  FixedArrayBase* to, ElementsKind from_kind,
1206  uint32_t to_start, int packed_size,
1207  int copy_size) {
1208  DisallowHeapAllocation no_allocation;
1209  switch (from_kind) {
1210  case FAST_SMI_ELEMENTS:
1211  CopyPackedSmiToDoubleElements(from, from_start, to, to_start,
1212  packed_size, copy_size);
1213  break;
1215  CopySmiToDoubleElements(from, from_start, to, to_start, copy_size);
1216  break;
1217  case FAST_DOUBLE_ELEMENTS:
1219  CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size);
1220  break;
1221  case FAST_ELEMENTS:
1222  case FAST_HOLEY_ELEMENTS:
1223  CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size);
1224  break;
1225  case DICTIONARY_ELEMENTS:
1226  CopyDictionaryToDoubleElements(from, from_start, to, to_start,
1227  copy_size);
1228  break;
1230  UNREACHABLE();
1231 
1232 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1233  case EXTERNAL_##TYPE##_ELEMENTS: \
1234  case TYPE##_ELEMENTS: \
1235  UNREACHABLE();
1237 #undef TYPED_ARRAY_CASE
1238  }
1239  }
1240 };
1241 
1242 
1244  : public FastDoubleElementsAccessor<
1245  FastPackedDoubleElementsAccessor,
1246  ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > {
1247  public:
1254 };
1255 
1256 
1258  : public FastDoubleElementsAccessor<
1259  FastHoleyDoubleElementsAccessor,
1260  ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > {
1261  public:
1262  friend class ElementsAccessorBase<
1269 };
1270 
1271 
1272 // Super class for all external element arrays.
1273 template<ElementsKind Kind>
1275  : public ElementsAccessorBase<TypedElementsAccessor<Kind>,
1276  ElementsKindTraits<Kind> > {
1277  public:
1278  explicit TypedElementsAccessor(const char* name)
1280  ElementsKindTraits<Kind> >(name) {}
1281 
1282  protected:
1285 
1286  friend class ElementsAccessorBase<AccessorClass,
1287  ElementsKindTraits<Kind> >;
1288 
1290  Handle<Object> receiver,
1291  Handle<JSObject> obj,
1292  uint32_t key,
1293  Handle<FixedArrayBase> backing_store) {
1294  if (key < AccessorClass::GetCapacityImpl(backing_store)) {
1295  return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
1296  } else {
1297  return backing_store->GetIsolate()->factory()->undefined_value();
1298  }
1299  }
1300 
1302  Handle<Object> receiver,
1303  Handle<JSObject> obj,
1304  uint32_t key,
1305  Handle<FixedArrayBase> backing_store) {
1306  return
1307  key < AccessorClass::GetCapacityImpl(backing_store)
1308  ? NONE : ABSENT;
1309  }
1310 
1312  Handle<JSObject> obj,
1313  Handle<Object> length,
1314  Handle<FixedArrayBase> backing_store) {
1315  // External arrays do not support changing their length.
1316  UNREACHABLE();
1317  return obj;
1318  }
1319 
1321  Handle<JSObject> obj,
1322  uint32_t key,
1324  // External arrays always ignore deletes.
1325  return obj->GetIsolate()->factory()->true_value();
1326  }
1327 
1328  static bool HasElementImpl(Handle<Object> receiver,
1329  Handle<JSObject> holder,
1330  uint32_t key,
1331  Handle<FixedArrayBase> backing_store) {
1332  uint32_t capacity =
1333  AccessorClass::GetCapacityImpl(backing_store);
1334  return key < capacity;
1335  }
1336 };
1337 
1338 
1339 
1340 #define EXTERNAL_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \
1341  typedef TypedElementsAccessor<EXTERNAL_##TYPE##_ELEMENTS> \
1342  External##Type##ElementsAccessor;
1343 
1345 #undef EXTERNAL_ELEMENTS_ACCESSOR
1346 
1347 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \
1348  typedef TypedElementsAccessor<TYPE##_ELEMENTS > \
1349  Fixed##Type##ElementsAccessor;
1350 
1352 #undef FIXED_ELEMENTS_ACCESSOR
1353 
1354 
1355 
1357  : public ElementsAccessorBase<DictionaryElementsAccessor,
1358  ElementsKindTraits<DICTIONARY_ELEMENTS> > {
1359  public:
1360  explicit DictionaryElementsAccessor(const char* name)
1363 
1364  // Adjusts the length of the dictionary backing store and returns the new
1365  // length according to ES5 section 15.4.5.2 behavior.
1367  Handle<FixedArrayBase> store,
1368  Handle<JSArray> array,
1369  Handle<Object> length_object,
1370  uint32_t length) {
1373  Isolate* isolate = array->GetIsolate();
1374  int capacity = dict->Capacity();
1375  uint32_t new_length = length;
1376  uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
1377  if (new_length < old_length) {
1378  // Find last non-deletable element in range of elements to be
1379  // deleted and adjust range accordingly.
1380  for (int i = 0; i < capacity; i++) {
1381  DisallowHeapAllocation no_gc;
1382  Object* key = dict->KeyAt(i);
1383  if (key->IsNumber()) {
1384  uint32_t number = static_cast<uint32_t>(key->Number());
1385  if (new_length <= number && number < old_length) {
1386  PropertyDetails details = dict->DetailsAt(i);
1387  if (!details.IsConfigurable()) new_length = number + 1;
1388  }
1389  }
1390  }
1391  if (new_length != length) {
1392  length_object = isolate->factory()->NewNumberFromUint(new_length);
1393  }
1394  }
1395 
1396  if (new_length == 0) {
1397  // Flush the backing store.
1398  JSObject::ResetElements(array);
1399  } else {
1400  DisallowHeapAllocation no_gc;
1401  // Remove elements that should be deleted.
1402  int removed_entries = 0;
1403  Handle<Object> the_hole_value = isolate->factory()->the_hole_value();
1404  for (int i = 0; i < capacity; i++) {
1405  Object* key = dict->KeyAt(i);
1406  if (key->IsNumber()) {
1407  uint32_t number = static_cast<uint32_t>(key->Number());
1408  if (new_length <= number && number < old_length) {
1409  dict->SetEntry(i, the_hole_value, the_hole_value);
1410  removed_entries++;
1411  }
1412  }
1413  }
1414 
1415  // Update the number of elements.
1416  dict->ElementsRemoved(removed_entries);
1417  }
1418  return length_object;
1419  }
1420 
1422  Handle<JSObject> obj,
1423  uint32_t key,
1425  Isolate* isolate = obj->GetIsolate();
1426  Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
1427  isolate);
1428  bool is_arguments =
1429  (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS);
1430  if (is_arguments) {
1431  backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate);
1432  }
1433  Handle<SeededNumberDictionary> dictionary =
1434  Handle<SeededNumberDictionary>::cast(backing_store);
1435  int entry = dictionary->FindEntry(key);
1436  if (entry != SeededNumberDictionary::kNotFound) {
1437  Handle<Object> result =
1438  SeededNumberDictionary::DeleteProperty(dictionary, entry, mode);
1439  if (*result == *isolate->factory()->false_value()) {
1441  // Deleting a non-configurable property in strict mode.
1442  Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
1443  Handle<Object> args[2] = { name, obj };
1444  THROW_NEW_ERROR(isolate, NewTypeError("strict_delete_property",
1445  HandleVector(args, 2)),
1446  Object);
1447  }
1448  return isolate->factory()->false_value();
1449  }
1450  Handle<FixedArray> new_elements =
1451  SeededNumberDictionary::Shrink(dictionary, key);
1452 
1453  if (is_arguments) {
1454  FixedArray::cast(obj->elements())->set(1, *new_elements);
1455  } else {
1456  obj->set_elements(*new_elements);
1457  }
1458  }
1459  return isolate->factory()->true_value();
1460  }
1461 
1462  static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1463  FixedArrayBase* to, ElementsKind from_kind,
1464  uint32_t to_start, int packed_size,
1465  int copy_size) {
1466  UNREACHABLE();
1467  }
1468 
1469 
1470  protected:
1473 
1475  Handle<JSObject> obj,
1476  uint32_t key,
1478  return DeleteCommon(obj, key, mode);
1479  }
1480 
1482  Handle<Object> receiver,
1483  Handle<JSObject> obj,
1484  uint32_t key,
1485  Handle<FixedArrayBase> store) {
1486  Handle<SeededNumberDictionary> backing_store =
1488  Isolate* isolate = backing_store->GetIsolate();
1489  int entry = backing_store->FindEntry(key);
1490  if (entry != SeededNumberDictionary::kNotFound) {
1491  Handle<Object> element(backing_store->ValueAt(entry), isolate);
1492  PropertyDetails details = backing_store->DetailsAt(entry);
1493  if (details.type() == CALLBACKS) {
1495  obj, receiver, element, key, obj);
1496  } else {
1497  return element;
1498  }
1499  }
1500  return isolate->factory()->the_hole_value();
1501  }
1502 
1504  Handle<Object> receiver,
1505  Handle<JSObject> obj,
1506  uint32_t key,
1507  Handle<FixedArrayBase> backing_store) {
1508  Handle<SeededNumberDictionary> dictionary =
1509  Handle<SeededNumberDictionary>::cast(backing_store);
1510  int entry = dictionary->FindEntry(key);
1511  if (entry != SeededNumberDictionary::kNotFound) {
1512  return dictionary->DetailsAt(entry).attributes();
1513  }
1514  return ABSENT;
1515  }
1516 
1518  Handle<Object> receiver,
1519  Handle<JSObject> obj,
1520  uint32_t key,
1521  Handle<FixedArrayBase> store) {
1522  Handle<SeededNumberDictionary> backing_store =
1524  int entry = backing_store->FindEntry(key);
1525  if (entry != SeededNumberDictionary::kNotFound &&
1526  backing_store->DetailsAt(entry).type() == CALLBACKS &&
1527  backing_store->ValueAt(entry)->IsAccessorPair()) {
1528  return handle(AccessorPair::cast(backing_store->ValueAt(entry)));
1529  }
1530  return MaybeHandle<AccessorPair>();
1531  }
1532 
1533  static bool HasElementImpl(Handle<Object> receiver,
1534  Handle<JSObject> holder,
1535  uint32_t key,
1536  Handle<FixedArrayBase> store) {
1537  Handle<SeededNumberDictionary> backing_store =
1539  return backing_store->FindEntry(key) != SeededNumberDictionary::kNotFound;
1540  }
1541 
1543  uint32_t index) {
1544  DisallowHeapAllocation no_gc;
1547  Object* key = dict->KeyAt(index);
1548  return Smi::cast(key)->value();
1549  }
1550 };
1551 
1552 
1554  SloppyArgumentsElementsAccessor,
1555  ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > {
1556  public:
1561  protected:
1562  friend class ElementsAccessorBase<
1565 
1567  Handle<Object> receiver,
1568  Handle<JSObject> obj,
1569  uint32_t key,
1570  Handle<FixedArrayBase> parameters) {
1571  Isolate* isolate = obj->GetIsolate();
1572  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
1573  Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
1574  if (!probe->IsTheHole()) {
1575  DisallowHeapAllocation no_gc;
1576  Context* context = Context::cast(parameter_map->get(0));
1577  int context_index = Handle<Smi>::cast(probe)->value();
1578  DCHECK(!context->get(context_index)->IsTheHole());
1579  return handle(context->get(context_index), isolate);
1580  } else {
1581  // Object is not mapped, defer to the arguments.
1582  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
1583  isolate);
1584  Handle<Object> result;
1586  isolate, result,
1587  ElementsAccessor::ForArray(arguments)->Get(
1588  receiver, obj, key, arguments),
1589  Object);
1590  // Elements of the arguments object in slow mode might be slow aliases.
1591  if (result->IsAliasedArgumentsEntry()) {
1592  DisallowHeapAllocation no_gc;
1593  AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result);
1594  Context* context = Context::cast(parameter_map->get(0));
1595  int context_index = entry->aliased_context_slot();
1596  DCHECK(!context->get(context_index)->IsTheHole());
1597  return handle(context->get(context_index), isolate);
1598  } else {
1599  return result;
1600  }
1601  }
1602  }
1603 
1605  Handle<Object> receiver,
1606  Handle<JSObject> obj,
1607  uint32_t key,
1608  Handle<FixedArrayBase> backing_store) {
1609  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(backing_store);
1610  Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
1611  if (!probe->IsTheHole()) {
1612  return NONE;
1613  } else {
1614  // If not aliased, check the arguments.
1615  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
1616  return ElementsAccessor::ForArray(arguments)->GetAttributes(
1617  receiver, obj, key, arguments);
1618  }
1619  }
1620 
1622  Handle<Object> receiver,
1623  Handle<JSObject> obj,
1624  uint32_t key,
1625  Handle<FixedArrayBase> parameters) {
1626  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
1627  Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
1628  if (!probe->IsTheHole()) {
1629  return MaybeHandle<AccessorPair>();
1630  } else {
1631  // If not aliased, check the arguments.
1632  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
1633  return ElementsAccessor::ForArray(arguments)->GetAccessorPair(
1634  receiver, obj, key, arguments);
1635  }
1636  }
1637 
1639  Handle<JSObject> obj,
1640  Handle<Object> length,
1641  Handle<FixedArrayBase> parameter_map) {
1642  // TODO(mstarzinger): This was never implemented but will be used once we
1643  // correctly implement [[DefineOwnProperty]] on arrays.
1644  UNIMPLEMENTED();
1645  return obj;
1646  }
1647 
1649  Handle<JSObject> obj,
1650  uint32_t key,
1652  Isolate* isolate = obj->GetIsolate();
1653  Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
1654  Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
1655  if (!probe->IsTheHole()) {
1656  // TODO(kmillikin): We could check if this was the last aliased
1657  // parameter, and revert to normal elements in that case. That
1658  // would enable GC of the context.
1659  parameter_map->set_the_hole(key + 2);
1660  } else {
1661  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
1662  if (arguments->IsDictionary()) {
1664  } else {
1665  // It's difficult to access the version of DeleteCommon that is declared
1666  // in the templatized super class, call the concrete implementation in
1667  // the class for the most generalized ElementsKind subclass.
1669  }
1670  }
1671  return isolate->factory()->true_value();
1672  }
1673 
1674  static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1675  FixedArrayBase* to, ElementsKind from_kind,
1676  uint32_t to_start, int packed_size,
1677  int copy_size) {
1678  UNREACHABLE();
1679  }
1680 
1682  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(backing_store);
1683  Handle<FixedArrayBase> arguments(
1684  FixedArrayBase::cast(parameter_map->get(1)));
1685  return Max(static_cast<uint32_t>(parameter_map->length() - 2),
1686  ForArray(arguments)->GetCapacity(arguments));
1687  }
1688 
1690  uint32_t index) {
1691  return index;
1692  }
1693 
1694  static bool HasElementImpl(Handle<Object> receiver,
1695  Handle<JSObject> holder,
1696  uint32_t key,
1697  Handle<FixedArrayBase> parameters) {
1698  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
1699  Handle<Object> probe = GetParameterMapArg(holder, parameter_map, key);
1700  if (!probe->IsTheHole()) {
1701  return true;
1702  } else {
1703  Isolate* isolate = holder->GetIsolate();
1704  Handle<FixedArrayBase> arguments(FixedArrayBase::cast(
1705  Handle<FixedArray>::cast(parameter_map)->get(1)), isolate);
1706  ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
1707  Handle<Object> value;
1709  isolate, value,
1710  accessor->Get(receiver, holder, key, arguments),
1711  false);
1712  return !value->IsTheHole();
1713  }
1714  }
1715 
1716  private:
1718  Handle<FixedArray> parameter_map,
1719  uint32_t key) {
1720  Isolate* isolate = holder->GetIsolate();
1721  uint32_t length = holder->IsJSArray()
1722  ? Smi::cast(Handle<JSArray>::cast(holder)->length())->value()
1723  : parameter_map->length();
1724  return key < (length - 2)
1725  ? handle(parameter_map->get(key + 2), isolate)
1726  : Handle<Object>::cast(isolate->factory()->the_hole_value());
1727  }
1728 };
1729 
1730 
1732  return elements_accessors_[ElementsKindForArray(*array)];
1733 }
1734 
1735 
1737  static ElementsAccessor* accessor_array[] = {
1738 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
1740 #undef ACCESSOR_ARRAY
1741  };
1742 
1743  STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
1745 
1746  elements_accessors_ = accessor_array;
1747 }
1748 
1749 
1751  if (elements_accessors_ == NULL) return;
1752 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
1754 #undef ACCESSOR_DELETE
1756 }
1757 
1758 
1759 template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
1761 MaybeHandle<Object> ElementsAccessorBase<ElementsAccessorSubclass,
1763  SetLengthImpl(Handle<JSObject> obj,
1764  Handle<Object> length,
1765  Handle<FixedArrayBase> backing_store) {
1766  Isolate* isolate = obj->GetIsolate();
1768 
1769  // Fast case: The new length fits into a Smi.
1770  Handle<Object> smi_length;
1771 
1772  if (Object::ToSmi(isolate, length).ToHandle(&smi_length) &&
1773  smi_length->IsSmi()) {
1774  const int value = Handle<Smi>::cast(smi_length)->value();
1775  if (value >= 0) {
1776  Handle<Object> new_length = ElementsAccessorSubclass::
1777  SetLengthWithoutNormalize(backing_store, array, smi_length, value);
1778  DCHECK(!new_length.is_null());
1779 
1780  // even though the proposed length was a smi, new_length could
1781  // still be a heap number because SetLengthWithoutNormalize doesn't
1782  // allow the array length property to drop below the index of
1783  // non-deletable elements.
1784  DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() ||
1785  new_length->IsUndefined());
1786  if (new_length->IsSmi()) {
1787  array->set_length(*Handle<Smi>::cast(new_length));
1788  return array;
1789  } else if (new_length->IsHeapNumber()) {
1790  array->set_length(*new_length);
1791  return array;
1792  }
1793  } else {
1794  return ThrowArrayLengthRangeError(isolate);
1795  }
1796  }
1797 
1798  // Slow case: The new length does not fit into a Smi or conversion
1799  // to slow elements is needed for other reasons.
1800  if (length->IsNumber()) {
1801  uint32_t value;
1802  if (length->ToArrayIndex(&value)) {
1803  Handle<SeededNumberDictionary> dictionary =
1805  DCHECK(!dictionary.is_null());
1806 
1808  SetLengthWithoutNormalize(dictionary, array, length, value);
1809  DCHECK(!new_length.is_null());
1810 
1811  DCHECK(new_length->IsNumber());
1812  array->set_length(*new_length);
1813  return array;
1814  } else {
1815  return ThrowArrayLengthRangeError(isolate);
1816  }
1817  }
1818 
1819  // Fall-back case: The new length is not a number so make the array
1820  // size one and set only element to length.
1821  Handle<FixedArray> new_backing_store = isolate->factory()->NewFixedArray(1);
1822  new_backing_store->set(0, *length);
1823  JSArray::SetContent(array, new_backing_store);
1824  return array;
1825 }
1826 
1827 
1829  Arguments* args) {
1830  // Optimize the case where there is one argument and the argument is a
1831  // small smi.
1832  if (args->length() == 1) {
1833  Handle<Object> obj = args->at<Object>(0);
1834  if (obj->IsSmi()) {
1835  int len = Handle<Smi>::cast(obj)->value();
1836  if (len > 0 && len < JSObject::kInitialMaxFastElementArray) {
1837  ElementsKind elements_kind = array->GetElementsKind();
1838  JSArray::Initialize(array, len, len);
1839 
1840  if (!IsFastHoleyElementsKind(elements_kind)) {
1841  elements_kind = GetHoleyElementsKind(elements_kind);
1842  JSObject::TransitionElementsKind(array, elements_kind);
1843  }
1844  return array;
1845  } else if (len == 0) {
1847  return array;
1848  }
1849  }
1850 
1851  // Take the argument as the length.
1852  JSArray::Initialize(array, 0);
1853 
1854  return JSArray::SetElementsLength(array, obj);
1855  }
1856 
1857  // Optimize the case where there are no parameters passed.
1858  if (args->length() == 0) {
1860  return array;
1861  }
1862 
1863  Factory* factory = array->GetIsolate()->factory();
1864 
1865  // Set length and elements on the array.
1866  int number_of_elements = args->length();
1868  array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS);
1869 
1870  // Allocate an appropriately typed elements array.
1871  ElementsKind elements_kind = array->GetElementsKind();
1873  if (IsFastDoubleElementsKind(elements_kind)) {
1875  factory->NewFixedDoubleArray(number_of_elements));
1876  } else {
1878  factory->NewFixedArrayWithHoles(number_of_elements));
1879  }
1880 
1881  // Fill in the content
1882  switch (array->GetElementsKind()) {
1884  case FAST_SMI_ELEMENTS: {
1886  for (int index = 0; index < number_of_elements; index++) {
1887  smi_elms->set(index, (*args)[index], SKIP_WRITE_BARRIER);
1888  }
1889  break;
1890  }
1891  case FAST_HOLEY_ELEMENTS:
1892  case FAST_ELEMENTS: {
1893  DisallowHeapAllocation no_gc;
1894  WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
1895  Handle<FixedArray> object_elms = Handle<FixedArray>::cast(elms);
1896  for (int index = 0; index < number_of_elements; index++) {
1897  object_elms->set(index, (*args)[index], mode);
1898  }
1899  break;
1900  }
1902  case FAST_DOUBLE_ELEMENTS: {
1903  Handle<FixedDoubleArray> double_elms =
1905  for (int index = 0; index < number_of_elements; index++) {
1906  double_elms->set(index, (*args)[index]->Number());
1907  }
1908  break;
1909  }
1910  default:
1911  UNREACHABLE();
1912  break;
1913  }
1914 
1915  array->set_elements(*elms);
1916  array->set_length(Smi::FromInt(number_of_elements));
1917  return array;
1918 }
1919 
1920 } } // namespace v8::internal
A JavaScript number value (ECMA-262, 4.3.20)
Definition: v8.h:2162
A single JavaScript stack frame.
Definition: v8.h:1358
Code * builtin(Name name)
Definition: builtins.h:254
static Context * cast(Object *context)
Definition: contexts.h:255
static bool HasElementImpl(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > store)
Definition: elements.cc:1533
DictionaryElementsAccessor(const char *name)
Definition: elements.cc:1360
static MUST_USE_RESULT MaybeHandle< Object > DeleteCommon(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:1421
static Handle< Object > SetLengthWithoutNormalize(Handle< FixedArrayBase > store, Handle< JSArray > array, Handle< Object > length_object, uint32_t length)
Definition: elements.cc:1366
static MUST_USE_RESULT PropertyAttributes GetAttributesImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1503
static MUST_USE_RESULT MaybeHandle< Object > GetImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > store)
Definition: elements.cc:1481
static uint32_t GetKeyForIndexImpl(Handle< FixedArrayBase > store, uint32_t index)
Definition: elements.cc:1542
static MUST_USE_RESULT MaybeHandle< AccessorPair > GetAccessorPairImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > store)
Definition: elements.cc:1517
static void CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind from_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1462
virtual MUST_USE_RESULT MaybeHandle< Object > Delete(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL OVERRIDE
Definition: elements.cc:1474
Object * ValueAt(int entry)
Definition: objects.h:3491
static Handle< Object > DeleteProperty(Handle< SeededNumberDictionary > dictionary, int entry, JSObject::DeleteMode mode)
Definition: objects.cc:14982
static MUST_USE_RESULT Handle< SeededNumberDictionary > Shrink(Handle< SeededNumberDictionary > dictionary, uint32_t key)
Definition: objects.h:3522
static void SetFastElementsCapacityAndLength(Handle< JSObject > obj, int capacity, int length)
Definition: elements.cc:699
virtual uint32_t GetCapacity(Handle< FixedArrayBase > backing_store) FINAL OVERRIDE
Definition: elements.cc:850
virtual bool HasElement(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store) FINAL OVERRIDE
Definition: elements.cc:600
virtual void SetCapacityAndLength(Handle< JSArray > array, int capacity, int length) FINAL OVERRIDE
Definition: elements.cc:691
static uint32_t GetKeyForIndexImpl(Handle< FixedArrayBase > backing_store, uint32_t index)
Definition: elements.cc:855
virtual void CopyElements(Handle< FixedArrayBase > from, uint32_t from_start, ElementsKind from_kind, Handle< FixedArrayBase > to, uint32_t to_start, int copy_size) FINAL OVERRIDE
Definition: elements.cc:718
static void ValidateContents(Handle< JSObject > holder, int length)
Definition: elements.cc:567
static bool HasElementImpl(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:592
ElementsAccessorBase(const char *name)
Definition: elements.cc:557
virtual MaybeHandle< FixedArray > AddElementsToFixedArray(Handle< Object > receiver, Handle< JSObject > holder, Handle< FixedArray > to, Handle< FixedArrayBase > from) FINAL OVERRIDE
Definition: elements.cc:768
ElementsTraitsParam::BackingStore BackingStore
Definition: elements.cc:561
static uint32_t GetCapacityImpl(Handle< FixedArrayBase > backing_store)
Definition: elements.cc:846
virtual MUST_USE_RESULT MaybeHandle< Object > SetLength(Handle< JSArray > array, Handle< Object > length) FINAL OVERRIDE
Definition: elements.cc:679
static MUST_USE_RESULT PropertyAttributes GetAttributesImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:649
static void ValidateImpl(Handle< JSObject > holder)
Definition: elements.cc:570
virtual MUST_USE_RESULT MaybeHandle< Object > Get(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store) FINAL OVERRIDE
Definition: elements.cc:609
static MUST_USE_RESULT MaybeHandle< AccessorPair > GetAccessorPairImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:671
virtual uint32_t GetKeyForIndex(Handle< FixedArrayBase > backing_store, uint32_t index) FINAL OVERRIDE
Definition: elements.cc:860
static void CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind from_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:711
virtual void CopyElements(JSObject *from_holder, uint32_t from_start, ElementsKind from_kind, Handle< FixedArrayBase > to, uint32_t to_start, int copy_size) FINAL OVERRIDE
Definition: elements.cc:737
ElementsTraitsParam ElementsTraits
Definition: elements.cc:560
virtual MUST_USE_RESULT PropertyAttributes GetAttributes(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store) FINAL OVERRIDE
Definition: elements.cc:640
DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase)
virtual MUST_USE_RESULT MaybeHandle< AccessorPair > GetAccessorPair(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store) FINAL OVERRIDE
Definition: elements.cc:662
static MUST_USE_RESULT MaybeHandle< Object > SetLengthImpl(Handle< JSObject > obj, Handle< Object > length, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1763
virtual void Validate(Handle< JSObject > holder) FINAL OVERRIDE
Definition: elements.cc:587
virtual MUST_USE_RESULT MaybeHandle< Object > Delete(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode) OVERRIDE=0
virtual ElementsKind kind() const FINAL OVERRIDE
Definition: elements.cc:563
static MUST_USE_RESULT MaybeHandle< Object > GetImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:628
static const int kCopyToEndAndInitializeToHole
Definition: elements.h:135
virtual MUST_USE_RESULT PropertyAttributes GetAttributes(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)=0
virtual MUST_USE_RESULT MaybeHandle< Object > Get(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)=0
static ElementsAccessor ** elements_accessors_
Definition: elements.h:211
static void InitializeOncePerProcess()
Definition: elements.cc:1736
static const int kCopyToEnd
Definition: elements.h:130
const char * name() const
Definition: elements.h:24
friend class SloppyArgumentsElementsAccessor
Definition: elements.h:195
static ElementsAccessor * ForArray(Handle< FixedArrayBase > array)
Definition: elements.cc:1731
virtual MUST_USE_RESULT MaybeHandle< AccessorPair > GetAccessorPair(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)=0
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
FastDoubleElementsAccessor(const char *name)
Definition: elements.cc:1193
static void CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind from_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1204
static void SetFastElementsCapacityAndLength(Handle< JSObject > obj, uint32_t capacity, uint32_t length)
Definition: elements.cc:1197
static void ValidateContents(Handle< JSObject > holder, int length)
Definition: elements.cc:1013
static Handle< Object > SetLengthWithoutNormalize(Handle< FixedArrayBase > backing_store, Handle< JSArray > array, Handle< Object > length_object, uint32_t length)
Definition: elements.cc:886
FastElementsAccessor(const char *name)
Definition: elements.cc:876
virtual MaybeHandle< Object > Delete(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL OVERRIDE
Definition: elements.cc:995
static Handle< Object > DeleteCommon(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode)
Definition: elements.cc:936
static bool HasElementImpl(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1002
KindTraits::BackingStore BackingStore
Definition: elements.cc:883
static void SetFastElementsCapacityAndLength(Handle< JSObject > obj, uint32_t capacity, uint32_t length)
Definition: elements.cc:1126
static void CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind from_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1080
static const int kHeaderSize
Definition: objects.h:2393
Object * get(int index)
Definition: objects-inl.h:2165
static Handle< Object > get(Handle< FixedDoubleArray > array, int index)
Definition: objects-inl.h:2234
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
bool is_null() const
Definition: handles.h:124
static const int kNotFound
Definition: objects.h:3283
Heap * GetHeap() const
Definition: objects-inl.h:1379
Isolate * GetIsolate() const
Definition: objects-inl.h:1387
bool InNewSpace(Object *object)
Definition: heap-inl.h:322
IncrementalMarking * incremental_marking()
Definition: heap.h:1205
void RightTrimFixedArray(FixedArrayBase *obj, int elements_to_trim)
Definition: heap.cc:3322
Builtins * builtins()
Definition: isolate.h:947
Factory * factory()
Definition: isolate.h:982
static MUST_USE_RESULT MaybeHandle< Object > SetElementsLength(Handle< JSArray > array, Handle< Object > length)
Definition: objects.cc:11167
static void SetContent(Handle< JSArray > array, Handle< FixedArrayBase > storage)
Definition: objects-inl.h:6986
static const int kPreallocatedArrayElements
Definition: objects.h:10069
static void Initialize(Handle< JSArray > array, int capacity, int length=0)
Definition: objects.cc:11083
static void ResetElements(Handle< JSObject > object)
Definition: objects.cc:4416
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithCallback(Handle< JSObject > object, Handle< Object > receiver, Handle< Object > structure, uint32_t index, Handle< Object > holder)
Definition: objects.cc:11812
static Handle< FixedArray > SetFastElementsCapacityAndLength(Handle< JSObject > object, int capacity, int length, SetFastElementsCapacitySmiMode smi_mode)
Definition: objects.cc:10982
static void SetFastDoubleElementsCapacityAndLength(Handle< JSObject > object, int capacity, int length)
Definition: objects.cc:11044
static void TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12706
static const int kInitialMaxFastElementArray
Definition: objects.h:2180
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1911
static Handle< FixedArray > EnsureWritableFastElements(Handle< JSObject > object)
Definition: objects.cc:383
static void ValidateElements(Handle< JSObject > object)
Definition: objects-inl.h:1561
static void EnsureCanContainElements(Handle< JSObject > object, Object **elements, uint32_t count, EnsureElementsMode mode)
Definition: objects-inl.h:1738
static Handle< SeededNumberDictionary > NormalizeElements(Handle< JSObject > object)
Definition: objects.cc:4459
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:811
InstanceType instance_type()
Definition: objects-inl.h:4323
static MUST_USE_RESULT MaybeHandle< Smi > ToSmi(Isolate *isolate, Handle< Object > object)
Definition: objects-inl.h:1081
static void CopyElementsImpl(FixedArrayBase *from, uint32_t from_start, FixedArrayBase *to, ElementsKind from_kind, uint32_t to_start, int packed_size, int copy_size)
Definition: elements.cc:1674
static uint32_t GetKeyForIndexImpl(Handle< FixedArrayBase > dict, uint32_t index)
Definition: elements.cc:1689
static MUST_USE_RESULT PropertyAttributes GetAttributesImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1604
static bool HasElementImpl(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > parameters)
Definition: elements.cc:1694
static MUST_USE_RESULT MaybeHandle< Object > SetLengthImpl(Handle< JSObject > obj, Handle< Object > length, Handle< FixedArrayBase > parameter_map)
Definition: elements.cc:1638
static Handle< Object > GetParameterMapArg(Handle< JSObject > holder, Handle< FixedArray > parameter_map, uint32_t key)
Definition: elements.cc:1717
virtual MUST_USE_RESULT MaybeHandle< Object > Delete(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL OVERRIDE
Definition: elements.cc:1648
static uint32_t GetCapacityImpl(Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1681
static MUST_USE_RESULT MaybeHandle< AccessorPair > GetAccessorPairImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > parameters)
Definition: elements.cc:1621
static MUST_USE_RESULT MaybeHandle< Object > GetImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > parameters)
Definition: elements.cc:1566
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
StackFrame * frame() const
Definition: frames.h:842
virtual MUST_USE_RESULT MaybeHandle< Object > Delete(Handle< JSObject > obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL OVERRIDE
Definition: elements.cc:1320
static bool HasElementImpl(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1328
ElementsKindTraits< Kind >::BackingStore BackingStore
Definition: elements.cc:1283
static MUST_USE_RESULT MaybeHandle< Object > GetImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1289
static MUST_USE_RESULT MaybeHandle< Object > SetLengthImpl(Handle< JSObject > obj, Handle< Object > length, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1311
TypedElementsAccessor< Kind > AccessorClass
Definition: elements.cc:1284
static MUST_USE_RESULT PropertyAttributes GetAttributesImpl(Handle< Object > receiver, Handle< JSObject > obj, uint32_t key, Handle< FixedArrayBase > backing_store)
Definition: elements.cc:1301
TypedElementsAccessor(const char *name)
Definition: elements.cc:1278
#define OVERRIDE
#define EXTERNAL_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size)
Definition: elements.cc:1340
#define ACCESSOR_ARRAY(Class, Kind, Store)
#define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size)
Definition: elements.cc:1347
#define ACCESSOR_DELETE(Class, Kind, Store)
#define ELEMENTS_TRAITS(Class, KindParam, Store)
Definition: elements.cc:113
#define ELEMENTS_LIST(V)
Definition: elements.cc:63
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
Definition: isolate.h:123
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
Definition: isolate.h:135
#define THROW_NEW_ERROR(isolate, call, T)
Definition: isolate.h:138
#define UNREACHABLE()
Definition: logging.h:30
#define UNIMPLEMENTED()
Definition: logging.h:28
#define DCHECK(condition)
Definition: logging.h:205
#define MUST_USE_RESULT
Definition: macros.h:266
int int32_t
Definition: unicode.cc:24
const int kPointerSize
Definition: globals.h:129
@ ALLOW_CONVERTED_DOUBLE_ELEMENTS
Definition: objects.h:1542
bool IsFastHoleyElementsKind(ElementsKind kind)
static const int kPackedSizeNotKnown
Definition: elements.cc:55
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:95
@ SKIP_WRITE_BARRIER
Definition: objects.h:235
@ UPDATE_WRITE_BARRIER
Definition: objects.h:235
static int min(int a, int b)
Definition: liveedit.cc:273
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
void CheckArrayAbuse(Handle< JSObject > obj, const char *op, uint32_t key, bool allow_appending)
Definition: elements.cc:496
unsigned int FastD2UI(double x)
const int kDoubleSize
Definition: globals.h:127
static bool HasKey(Handle< FixedArray > array, Handle< Object > key_handle)
Definition: elements.cc:126
void MemsetPointer(T **dest, U *value, int counter)
Definition: utils.h:1183
static void CopyDoubleToDoubleElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:301
const int kElementsKindCount
Definition: elements-kind.h:66
static ElementsKind ElementsKindForArray(FixedArrayBase *array)
Definition: elements.cc:1039
double FastI2D(int x)
Definition: conversions.h:64
@ FIXED_DOUBLE_ARRAY_TYPE
Definition: objects.h:692
@ FIXED_ARRAY_TYPE
Definition: objects.h:717
@ FAST_HOLEY_DOUBLE_ELEMENTS
Definition: elements-kind.h:27
@ SLOPPY_ARGUMENTS_ELEMENTS
Definition: elements-kind.h:31
@ FAST_HOLEY_SMI_ELEMENTS
Definition: elements-kind.h:17
bool IsFastDoubleElementsKind(ElementsKind kind)
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
static void CopySmiToDoubleElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:334
bool IsFastPackedElementsKind(ElementsKind kind)
const bool FLAG_enable_slow_asserts
Definition: checks.h:31
static MUST_USE_RESULT MaybeHandle< Object > ThrowArrayLengthRangeError(Isolate *isolate)
Definition: elements.cc:143
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
static void CopyDictionaryToObjectElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, ElementsKind to_kind, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:200
static void CopyDictionaryToDoubleElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:441
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
byte * Address
Definition: globals.h:101
bool IsFastElementsKind(ElementsKind kind)
void PrintF(const char *format,...)
Definition: utils.cc:80
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: utils.h:1100
int32_t DoubleToInt32(double x)
void CopyWords(T *dst, const T *src, size_t num_words)
Definition: utils.h:1112
static void CopyObjectToDoubleElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:407
static void CopyDoubleToObjectElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, ElementsKind to_kind, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:253
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
static void TraceTopFrame(Isolate *isolate)
Definition: elements.cc:476
bool IsFastSmiElementsKind(ElementsKind kind)
int FastD2IChecked(double x)
Definition: conversions.h:46
bool IsFastObjectElementsKind(ElementsKind kind)
static void CopyObjectToObjectElements(FixedArrayBase *from_base, ElementsKind from_kind, uint32_t from_start, FixedArrayBase *to_base, ElementsKind to_kind, uint32_t to_start, int raw_copy_size)
Definition: elements.cc:150
MaybeHandle< Object > ArrayConstructInitializeElements(Handle< JSArray > array, Arguments *args)
Definition: elements.cc:1828
static void CopyPackedSmiToDoubleElements(FixedArrayBase *from_base, uint32_t from_start, FixedArrayBase *to_base, uint32_t to_start, int packed_size, int raw_copy_size)
Definition: elements.cc:368
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define TYPED_ARRAYS(V)
Definition: objects.h:4433
PropertyAttributes
@ ABSENT
@ NONE