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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
/* -*- 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 frontend_StencilXdr_h
#define frontend_StencilXdr_h
#include "mozilla/RefPtr.h" // RefPtr
#include "frontend/ParserAtom.h" // ParserAtom, ParserAtomSpan
#include "frontend/Stencil.h" // BitIntStencil, ScopeStencil, BaseParserScopeData
#include "vm/Xdr.h" // XDRMode, XDRResult, XDRState
namespace JS {
class DecodeOptions;
} // namespace JS
namespace js {
class LifoAlloc;
class ObjLiteralStencil;
class ScriptSource;
class SharedImmutableScriptData;
class XDRStencilDecoder;
class XDRStencilEncoder;
namespace frontend {
struct CompilationStencil;
struct ExtensibleCompilationStencil;
struct SharedDataContainer;
// Check that we can copy data to disk and restore it in another instance of
// the program in a different address space.
template <typename DataT>
struct CanCopyDataToDisk {
// Check that the object is fully packed, to save disk space.
#ifdef __cpp_lib_has_unique_object_representations
static constexpr bool unique_repr =
std::has_unique_object_representations<DataT>();
#else
static constexpr bool unique_repr = true;
#endif
// Approximation which assumes that 32bits variant of the class would not
// have pointers if the 64bits variant does not have pointer.
static constexpr bool no_pointer =
alignof(DataT) < alignof(void*) || sizeof(void*) == sizeof(uint32_t);
static constexpr bool value = unique_repr && no_pointer;
};
// This is just a namespace class that can be used in friend declarations,
// so that the statically declared XDR methods within have access to the
// relevant struct internals.
class StencilXDR {
private:
template <XDRMode mode>
[[nodiscard]] static XDRResult codeSourceUnretrievableUncompressed(
XDRState<mode>* xdr, ScriptSource* ss, uint8_t sourceCharSize,
uint32_t uncompressedLength);
template <typename Unit,
template <typename U, SourceRetrievable CanRetrieve> class Data,
XDRMode mode>
static void codeSourceRetrievable(ScriptSource* ss);
template <typename Unit, XDRMode mode>
[[nodiscard]] static XDRResult codeSourceUncompressedData(
XDRState<mode>* const xdr, ScriptSource* const ss);
template <typename Unit, XDRMode mode>
[[nodiscard]] static XDRResult codeSourceCompressedData(
XDRState<mode>* const xdr, ScriptSource* const ss);
template <typename Unit, XDRMode mode>
static void codeSourceRetrievableData(ScriptSource* ss);
template <XDRMode mode>
[[nodiscard]] static XDRResult codeSourceData(XDRState<mode>* const xdr,
ScriptSource* const ss);
public:
template <XDRMode mode>
static XDRResult codeSource(XDRState<mode>* xdr,
const JS::DecodeOptions* maybeOptions,
RefPtr<ScriptSource>& source);
template <XDRMode mode>
static XDRResult codeBigInt(XDRState<mode>* xdr, LifoAlloc& alloc,
BigIntStencil& stencil);
template <XDRMode mode>
static XDRResult codeObjLiteral(XDRState<mode>* xdr, LifoAlloc& alloc,
ObjLiteralStencil& stencil);
template <XDRMode mode>
static XDRResult codeScopeData(XDRState<mode>* xdr, LifoAlloc& alloc,
ScopeStencil& stencil,
BaseParserScopeData*& baseScopeData);
template <XDRMode mode>
static XDRResult codeSharedData(XDRState<mode>* xdr,
RefPtr<SharedImmutableScriptData>& sisd);
template <XDRMode mode>
static XDRResult codeSharedDataContainer(XDRState<mode>* xdr,
SharedDataContainer& sharedData);
template <XDRMode mode>
static XDRResult codeParserAtom(XDRState<mode>* xdr, LifoAlloc& alloc,
ParserAtom** atomp);
template <XDRMode mode>
static XDRResult codeParserAtomSpan(XDRState<mode>* xdr, LifoAlloc& alloc,
ParserAtomSpan& parserAtomData);
template <XDRMode mode>
static XDRResult codeModuleRequest(XDRState<mode>* xdr,
StencilModuleRequest& stencil);
template <XDRMode mode>
static XDRResult codeModuleRequestVector(
XDRState<mode>* xdr, StencilModuleMetadata::RequestVector& vector);
template <XDRMode mode>
static XDRResult codeModuleEntry(XDRState<mode>* xdr,
StencilModuleEntry& stencil);
template <XDRMode mode>
static XDRResult codeModuleEntryVector(
XDRState<mode>* xdr, StencilModuleMetadata::EntryVector& vector);
template <XDRMode mode>
static XDRResult codeModuleMetadata(XDRState<mode>* xdr,
StencilModuleMetadata& stencil);
static XDRResult checkCompilationStencil(XDRStencilEncoder* encoder,
const CompilationStencil& stencil);
static XDRResult checkCompilationStencil(
const ExtensibleCompilationStencil& stencil);
template <XDRMode mode>
static XDRResult codeCompilationStencil(XDRState<mode>* xdr,
CompilationStencil& stencil);
};
} /* namespace frontend */
/*
* The structure of the Stencil XDR buffer is:
*
* 1. Version
* 2. length of content
* 3. checksum of content
* 4. content
* a. ScriptSource
* b. CompilationStencil
*/
/*
* The stencil decoder accepts `range` as input.
*
* The decoded stencils are outputted to the default-initialized
* `stencil` parameter of `codeStencil` method.
*
* The decoded stencils borrow the input `buffer`/`range`, and the consumer
* has to keep the buffer alive while the decoded stencils are alive.
*/
class XDRStencilDecoder : public XDRState<XDR_DECODE> {
using Base = XDRState<XDR_DECODE>;
public:
XDRStencilDecoder(FrontendContext* fc, const JS::TranscodeRange& range)
: Base(fc, range) {
MOZ_ASSERT(JS::IsTranscodingBytecodeAligned(range.begin().get()));
}
XDRResult codeStencil(const JS::DecodeOptions& options,
frontend::CompilationStencil& stencil);
const JS::DecodeOptions& options() {
MOZ_ASSERT(options_);
return *options_;
}
private:
const JS::DecodeOptions* options_ = nullptr;
};
class XDRStencilEncoder : public XDRState<XDR_ENCODE> {
using Base = XDRState<XDR_ENCODE>;
public:
XDRStencilEncoder(FrontendContext* fc, JS::TranscodeBuffer& buffer)
: Base(fc, buffer, buffer.length()) {
// NOTE: If buffer is empty, buffer.begin() doesn't point valid buffer.
MOZ_ASSERT_IF(!buffer.empty(),
JS::IsTranscodingBytecodeAligned(buffer.begin()));
MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(buffer.length()));
}
XDRResult codeStencil(const RefPtr<ScriptSource>& source,
const frontend::CompilationStencil& stencil);
XDRResult codeStencil(const frontend::CompilationStencil& stencil);
};
} /* namespace js */
#endif /* frontend_StencilXdr_h */
|