1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef vm_ArrayObject_inl_h
8 #define vm_ArrayObject_inl_h
9 
10 #include "vm/ArrayObject.h"
11 
12 #include "gc/Allocator.h"
13 #include "gc/GCProbes.h"
14 #include "vm/StringType.h"
15 
16 #include "vm/JSObject-inl.h"
17 #include "vm/ObjectOperations-inl.h"  // js::GetElement
18 
19 namespace js {
20 
createArrayInternal(JSContext * cx,gc::AllocKind kind,gc::InitialHeap heap,HandleShape shape,AutoSetNewObjectMetadata &,gc::AllocSite * site)21 /* static */ inline ArrayObject* ArrayObject::createArrayInternal(
22     JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap, HandleShape shape,
23     AutoSetNewObjectMetadata&, gc::AllocSite* site) {
24   const JSClass* clasp = shape->getObjectClass();
25   MOZ_ASSERT(shape);
26   MOZ_ASSERT(clasp == &ArrayObject::class_);
27   MOZ_ASSERT(clasp->isNativeObject());
28   MOZ_ASSERT_IF(clasp->hasFinalize(), heap == gc::TenuredHeap);
29 
30   // Arrays can use their fixed slots to store elements, so can't have shapes
31   // which allow named properties to be stored in the fixed slots.
32   MOZ_ASSERT(shape->numFixedSlots() == 0);
33 
34   size_t nDynamicSlots = calculateDynamicSlots(0, shape->slotSpan(), clasp);
35   JSObject* obj =
36       js::AllocateObject(cx, kind, nDynamicSlots, heap, clasp, site);
37   if (!obj) {
38     return nullptr;
39   }
40 
41   ArrayObject* aobj = static_cast<ArrayObject*>(obj);
42   aobj->initShape(shape);
43   // NOTE: Dynamic slots are created internally by Allocate<JSObject>.
44   if (!nDynamicSlots) {
45     aobj->initEmptyDynamicSlots();
46   }
47 
48   MOZ_ASSERT(clasp->shouldDelayMetadataBuilder());
49   cx->realm()->setObjectPendingMetadata(cx, aobj);
50 
51   return aobj;
52 }
53 
finishCreateArray(ArrayObject * obj,HandleShape shape,AutoSetNewObjectMetadata & metadata)54 /* static */ inline ArrayObject* ArrayObject::finishCreateArray(
55     ArrayObject* obj, HandleShape shape, AutoSetNewObjectMetadata& metadata) {
56   size_t span = shape->slotSpan();
57   if (span) {
58     obj->initializeSlotRange(0, span);
59   }
60 
61   gc::gcprobes::CreateObject(obj);
62 
63   return obj;
64 }
65 
createArray(JSContext * cx,gc::AllocKind kind,gc::InitialHeap heap,HandleShape shape,uint32_t length,AutoSetNewObjectMetadata & metadata,gc::AllocSite * site)66 /* static */ inline ArrayObject* ArrayObject::createArray(
67     JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap, HandleShape shape,
68     uint32_t length, AutoSetNewObjectMetadata& metadata, gc::AllocSite* site) {
69   ArrayObject* obj = createArrayInternal(cx, kind, heap, shape, metadata, site);
70   if (!obj) {
71     return nullptr;
72   }
73 
74   uint32_t capacity =
75       gc::GetGCKindSlots(kind) - ObjectElements::VALUES_PER_HEADER;
76 
77   obj->setFixedElements();
78   new (obj->getElementsHeader()) ObjectElements(capacity, length);
79 
80   return finishCreateArray(obj, shape, metadata);
81 }
82 
83 }  // namespace js
84 
85 #endif  // vm_ArrayObject_inl_h
86