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/. */
8 * Inline definitions of the CellAllocator methods.
10 * This is included from JSContext-inl.h for the definiton of JSContext::newCell
11 * and shouldn't need to be included elsewhere.
14 #ifndef gc_Allocator_inl_h
15 #define gc_Allocator_inl_h
17 #include "gc/Allocator.h"
22 #include "js/RootingAPI.h"
24 #include "gc/Nursery-inl.h"
29 template <typename T
, AllowGC allowGC
, typename
... Args
>
30 T
* CellAllocator::NewCell(JSContext
* cx
, Args
&&... args
) {
31 static_assert(std::is_base_of_v
<gc::Cell
, T
>);
33 // Objects. See the valid parameter list in NewObject, above.
34 if constexpr (std::is_base_of_v
<JSObject
, T
>) {
35 return NewObject
<T
, allowGC
>(cx
, std::forward
<Args
>(args
)...);
39 else if constexpr (std::is_base_of_v
<JS::BigInt
, T
>) {
40 return NewBigInt
<T
, allowGC
>(cx
, std::forward
<Args
>(args
)...);
43 // "Normal" strings (all of which can be nursery allocated). Atoms and
44 // external strings will fall through to the generic code below. All other
45 // strings go through NewString, which will forward the arguments to the
46 // appropriate string class's constructor.
47 else if constexpr (std::is_base_of_v
<JSString
, T
> &&
48 !std::is_base_of_v
<JSAtom
, T
> &&
49 !std::is_base_of_v
<JSExternalString
, T
>) {
50 return NewString
<T
, allowGC
>(cx
, std::forward
<Args
>(args
)...);
54 // Allocate a new tenured GC thing that's not nursery-allocatable. Use
55 // cx->newCell<T>(...), where the parameters are forwarded to the type's
57 return NewTenuredCell
<T
, allowGC
>(cx
, std::forward
<Args
>(args
)...);
61 template <typename T
, AllowGC allowGC
, typename
... Args
>
63 T
* CellAllocator::NewString(JSContext
* cx
, gc::Heap heap
, Args
&&... args
) {
64 static_assert(std::is_base_of_v
<JSString
, T
>);
65 gc::AllocKind kind
= gc::MapTypeToAllocKind
<T
>::kind
;
66 void* ptr
= AllocNurseryOrTenuredCell
<JS::TraceKind::String
, allowGC
>(
67 cx
, kind
, sizeof(T
), heap
, nullptr);
68 if (MOZ_UNLIKELY(!ptr
)) {
71 return new (mozilla::KnownNotNull
, ptr
) T(std::forward
<Args
>(args
)...);
74 template <typename T
, AllowGC allowGC
>
76 T
* CellAllocator::NewBigInt(JSContext
* cx
, Heap heap
) {
77 void* ptr
= AllocNurseryOrTenuredCell
<JS::TraceKind::BigInt
, allowGC
>(
78 cx
, gc::AllocKind::BIGINT
, sizeof(T
), heap
, nullptr);
79 if (MOZ_UNLIKELY(!ptr
)) {
82 return new (mozilla::KnownNotNull
, ptr
) T();
85 template <typename T
, AllowGC allowGC
>
87 T
* CellAllocator::NewObject(JSContext
* cx
, gc::AllocKind kind
, gc::Heap heap
,
88 const JSClass
* clasp
, gc::AllocSite
* site
) {
89 MOZ_ASSERT(IsObjectAllocKind(kind
));
90 MOZ_ASSERT_IF(heap
!= gc::Heap::Tenured
&& clasp
->hasFinalize() &&
91 !clasp
->isProxyObject(),
92 CanNurseryAllocateFinalizedClass(clasp
));
93 size_t thingSize
= JSObject::thingSize(kind
);
94 void* cell
= AllocNurseryOrTenuredCell
<JS::TraceKind::Object
, allowGC
>(
95 cx
, kind
, thingSize
, heap
, site
);
96 if (MOZ_UNLIKELY(!cell
)) {
99 return new (mozilla::KnownNotNull
, cell
) T();
102 template <JS::TraceKind traceKind
, AllowGC allowGC
>
104 void* CellAllocator::AllocNurseryOrTenuredCell(JSContext
* cx
,
105 gc::AllocKind allocKind
,
106 size_t thingSize
, gc::Heap heap
,
108 MOZ_ASSERT(IsNurseryAllocable(allocKind
));
109 MOZ_ASSERT(MapAllocToTraceKind(allocKind
) == traceKind
);
110 MOZ_ASSERT(thingSize
== Arena::thingSize(allocKind
));
111 MOZ_ASSERT_IF(site
&& site
->initialHeap() == Heap::Tenured
,
112 heap
== Heap::Tenured
);
114 if (!PreAllocChecks
<allowGC
>(cx
, allocKind
)) {
118 JS::Zone
* zone
= cx
->zone();
119 gc::Heap minHeapToTenure
= CheckedHeap(zone
->minHeapToTenure(traceKind
));
120 if (CheckedHeap(heap
) < minHeapToTenure
) {
122 site
= zone
->unknownAllocSite(traceKind
);
125 void* ptr
= cx
->nursery().tryAllocateCell(site
, thingSize
, traceKind
);
126 if (MOZ_LIKELY(ptr
)) {
130 return RetryNurseryAlloc
<allowGC
>(cx
, traceKind
, allocKind
, thingSize
,
134 return TryNewTenuredCell
<allowGC
>(cx
, allocKind
, thingSize
);
138 MOZ_ALWAYS_INLINE
gc::Heap
CellAllocator::CheckedHeap(gc::Heap heap
) {
139 if (heap
> Heap::Tenured
) {
140 // This helps the compiler to see that nursery allocation is never
141 // possible if Heap::Tenured is specified.
142 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad gc::Heap value");
148 template <typename T
, AllowGC allowGC
, typename
... Args
>
150 T
* CellAllocator::NewTenuredCell(JSContext
* cx
, Args
&&... args
) {
151 gc::AllocKind kind
= gc::MapTypeToAllocKind
<T
>::kind
;
152 void* cell
= AllocTenuredCell
<allowGC
>(cx
, kind
, sizeof(T
));
153 if (MOZ_UNLIKELY(!cell
)) {
156 return new (mozilla::KnownNotNull
, cell
) T(std::forward
<Args
>(args
)...);
162 #endif // gc_Allocator_inl_h