1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef gc_Allocator_h
#define gc_Allocator_h
#include "mozilla/OperatorNewExtensions.h"
#include <stdint.h>
#include "gc/AllocKind.h"
#include "gc/GCEnum.h"
#include "js/TypeDecls.h"
namespace js {
namespace gc {
class AllocSite;
struct Cell;
class TenuredCell;
// Allocator implementation functions. SpiderMonkey code outside this file
// should use:
//
// cx->newCell<T>(...)
//
// or optionally:
//
// cx->newCell<T, AllowGC::NoGC>(...)
//
// `friend` js::gc::CellAllocator in a subtype T of Cell in order to allow it to
// be allocated with cx->newCell<T>(...). The friend declaration will allow
// calling T's constructor.
//
// The parameters will be passed to a type-specific function or constructor. For
// nursery-allocatable types, see e.g. the NewString, NewObject, and NewBigInt
// methods. For all other types, the parameters will be forwarded to the
// constructor.
class CellAllocator {
public:
// This is the entry point for all allocation, though callers should still not
// use this directly. Use cx->newCell<T>(...) instead.
//
// After a successful allocation the caller must fully initialize the thing
// before calling any function that can potentially trigger GC. This will
// ensure that GC tracing never sees junk values stored in the partially
// initialized thing.
template <typename T, js::AllowGC allowGC = CanGC, typename... Args>
static inline T* NewCell(JSContext* cx, Args&&... args);
private:
template <AllowGC allowGC>
static void* RetryNurseryAlloc(JSContext* cx, JS::TraceKind traceKind,
AllocKind allocKind, size_t thingSize,
AllocSite* site);
template <AllowGC allowGC>
static void* TryNewTenuredCell(JSContext* cx, AllocKind kind,
size_t thingSize);
#if defined(DEBUG) || defined(JS_GC_ZEAL) || defined(JS_OOM_BREAKPOINT)
template <AllowGC allowGC>
static bool PreAllocChecks(JSContext* cx, AllocKind kind);
#else
template <AllowGC allowGC>
static bool PreAllocChecks(JSContext* cx, AllocKind kind) {
return true;
}
#endif
#ifdef DEBUG
static void CheckIncrementalZoneState(JSContext* cx, void* ptr);
#endif
static inline gc::Heap CheckedHeap(gc::Heap heap);
// Allocate a cell in the nursery, unless |heap| is Heap::Tenured or nursery
// allocation is disabled for |traceKind| in the current zone.
template <JS::TraceKind traceKind, AllowGC allowGC>
static void* AllocNurseryOrTenuredCell(JSContext* cx, gc::AllocKind allocKind,
size_t thingSize, gc::Heap heap,
AllocSite* site);
// Allocate a cell in the tenured heap.
template <AllowGC allowGC>
static void* AllocTenuredCell(JSContext* cx, gc::AllocKind kind, size_t size);
// Allocate a string. Use cx->newCell<T>([heap]).
//
// Use for nursery-allocatable strings. Returns a value cast to the correct
// type. Non-nursery-allocatable strings will go through the fallback
// tenured-only allocation path.
template <typename T, AllowGC allowGC, typename... Args>
static T* NewString(JSContext* cx, gc::Heap heap, Args&&... args);
template <typename T, AllowGC allowGC>
static T* NewBigInt(JSContext* cx, Heap heap);
template <typename T, AllowGC allowGC>
static T* NewObject(JSContext* cx, gc::AllocKind kind, gc::Heap heap,
const JSClass* clasp, gc::AllocSite* site = nullptr);
// Allocate all other kinds of GC thing.
template <typename T, AllowGC allowGC, typename... Args>
static T* NewTenuredCell(JSContext* cx, Args&&... args);
};
} // namespace gc
} // namespace js
#endif // gc_Allocator_h
|