Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/GCTrace.h"
13 : #include "vm/String.h"
14 :
15 : #include "jsgcinlines.h"
16 : #include "jsobjinlines.h"
17 :
18 : #include "vm/TypeInference-inl.h"
19 :
20 : namespace js {
21 :
22 : inline void
23 3603 : ArrayObject::setLength(JSContext* cx, uint32_t length)
24 : {
25 3603 : MOZ_ASSERT(lengthIsWritable());
26 3603 : MOZ_ASSERT_IF(length != getElementsHeader()->length, !denseElementsAreFrozen());
27 :
28 3603 : if (length > INT32_MAX) {
29 : /* Track objects with overflowing lengths in type information. */
30 0 : MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
31 : }
32 :
33 3603 : getElementsHeader()->length = length;
34 3603 : }
35 :
36 : /* static */ inline ArrayObject*
37 3668 : ArrayObject::createArrayInternal(JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap,
38 : HandleShape shape, HandleObjectGroup group,
39 : AutoSetNewObjectMetadata&)
40 : {
41 : // Create a new array and initialize everything except for its elements.
42 3668 : MOZ_ASSERT(shape && group);
43 3668 : MOZ_ASSERT(group->clasp() == shape->getObjectClass());
44 3668 : MOZ_ASSERT(group->clasp() == &ArrayObject::class_);
45 3668 : MOZ_ASSERT_IF(group->clasp()->hasFinalize(), heap == gc::TenuredHeap);
46 3668 : MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(),
47 : heap == js::gc::TenuredHeap);
48 3668 : MOZ_ASSERT(group->clasp()->shouldDelayMetadataBuilder());
49 :
50 : // Arrays can use their fixed slots to store elements, so can't have shapes
51 : // which allow named properties to be stored in the fixed slots.
52 3668 : MOZ_ASSERT(shape->numFixedSlots() == 0);
53 :
54 3668 : size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan(), group->clasp());
55 3668 : JSObject* obj = Allocate<JSObject>(cx, kind, nDynamicSlots, heap, group->clasp());
56 3668 : if (!obj)
57 0 : return nullptr;
58 :
59 3668 : static_cast<ArrayObject*>(obj)->shape_.init(shape);
60 3668 : static_cast<ArrayObject*>(obj)->group_.init(group);
61 :
62 3668 : cx->compartment()->setObjectPendingMetadata(cx, obj);
63 3668 : return &obj->as<ArrayObject>();
64 : }
65 :
66 : /* static */ inline ArrayObject*
67 3668 : ArrayObject::finishCreateArray(ArrayObject* obj, HandleShape shape, AutoSetNewObjectMetadata& metadata)
68 : {
69 3668 : size_t span = shape->slotSpan();
70 3668 : if (span)
71 58 : obj->initializeSlotRange(0, span);
72 :
73 3668 : gc::TraceCreateObject(obj);
74 :
75 3668 : return obj;
76 : }
77 :
78 : /* static */ inline ArrayObject*
79 2829 : ArrayObject::createArray(JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap,
80 : HandleShape shape, HandleObjectGroup group,
81 : uint32_t length, AutoSetNewObjectMetadata& metadata)
82 : {
83 2829 : ArrayObject* obj = createArrayInternal(cx, kind, heap, shape, group, metadata);
84 2829 : if (!obj)
85 0 : return nullptr;
86 :
87 2829 : uint32_t capacity = gc::GetGCKindSlots(kind) - ObjectElements::VALUES_PER_HEADER;
88 :
89 2829 : obj->setFixedElements();
90 2829 : new (obj->getElementsHeader()) ObjectElements(capacity, length);
91 :
92 2829 : return finishCreateArray(obj, shape, metadata);
93 : }
94 :
95 : /* static */ inline ArrayObject*
96 839 : ArrayObject::createCopyOnWriteArray(JSContext* cx, gc::InitialHeap heap,
97 : HandleArrayObject sharedElementsOwner)
98 : {
99 839 : MOZ_ASSERT(sharedElementsOwner->getElementsHeader()->isCopyOnWrite());
100 839 : MOZ_ASSERT(sharedElementsOwner->getElementsHeader()->ownerObject() == sharedElementsOwner);
101 :
102 : // Use the smallest allocation kind for the array, as it can't have any
103 : // fixed slots (see the assert in createArrayInternal) and will not be using
104 : // its fixed elements.
105 839 : gc::AllocKind kind = gc::AllocKind::OBJECT0_BACKGROUND;
106 :
107 1678 : AutoSetNewObjectMetadata metadata(cx);
108 1678 : RootedShape shape(cx, sharedElementsOwner->lastProperty());
109 1678 : RootedObjectGroup group(cx, sharedElementsOwner->group());
110 839 : ArrayObject* obj = createArrayInternal(cx, kind, heap, shape, group, metadata);
111 839 : if (!obj)
112 0 : return nullptr;
113 :
114 839 : obj->elements_ = sharedElementsOwner->getDenseElementsAllowCopyOnWrite();
115 :
116 839 : return finishCreateArray(obj, shape, metadata);
117 : }
118 :
119 : } // namespace js
120 :
121 : #endif // vm_ArrayObject_inl_h
|