summaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/src/ds/LifoAlloc.h16
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp5
-rw-r--r--js/src/frontend/ParseNode.cpp2
-rw-r--r--js/src/frontend/Parser.cpp82
-rw-r--r--js/src/gc/Marking.cpp30
-rw-r--r--js/src/vm/Scope.cpp20
-rw-r--r--js/src/vm/Scope.h120
7 files changed, 180 insertions, 95 deletions
diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h
index f349cd476..b4e9c3418 100644
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -15,6 +15,8 @@
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
+#include <new>
+
// This data structure supports stacky LIFO allocation (mark/release and
// LifoAllocScope). It does not maintain one contiguous segment; instead, it
// maintains a bunch of linked memory segments. In order to prevent malloc/free
@@ -285,6 +287,20 @@ class LifoAlloc
return allocImpl(n);
}
+ template<typename T, typename... Args>
+ MOZ_ALWAYS_INLINE T*
+ allocInSize(size_t n, Args&&... args)
+ {
+ MOZ_ASSERT(n >= sizeof(T), "must request enough space to store a T");
+ static_assert(alignof(T) <= detail::LIFO_ALLOC_ALIGN,
+ "LifoAlloc must provide enough alignment to store T");
+ void* ptr = alloc(n);
+ if (!ptr)
+ return nullptr;
+
+ return new (ptr) T(mozilla::Forward<Args>(args)...);
+ }
+
MOZ_ALWAYS_INLINE
void* allocInfallible(size_t n) {
AutoEnterOOMUnsafeRegion oomUnsafe;
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index c7c615ccf..4eb7bf880 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -319,7 +319,7 @@ ScopeKindIsInBody(ScopeKind kind)
static inline void
MarkAllBindingsClosedOver(LexicalScope::Data& data)
{
- BindingName* names = data.names;
+ TrailingNamesArray& names = data.trailingNames;
for (uint32_t i = 0; i < data.length; i++)
names[i] = BindingName(names[i].name(), true);
}
@@ -8978,7 +8978,8 @@ BytecodeEmitter::isRestParameter(ParseNode* pn, bool* result)
if (bindings->nonPositionalFormalStart > 0) {
// |paramName| can be nullptr when the rest destructuring syntax is
// used: `function f(...[]) {}`.
- JSAtom* paramName = bindings->names[bindings->nonPositionalFormalStart - 1].name();
+ JSAtom* paramName =
+ bindings->trailingNames[bindings->nonPositionalFormalStart - 1].name();
*result = paramName && name == paramName;
return true;
}
diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp
index ece3a45df..91f17625c 100644
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -838,7 +838,7 @@ LexicalScopeNode::dump(int indent)
if (!isEmptyScope()) {
LexicalScope::Data* bindings = scopeBindings();
for (uint32_t i = 0; i < bindings->length; i++) {
- JSAtom* name = bindings->names[i].name();
+ JSAtom* name = bindings->trailingNames[i].name();
JS::AutoCheckCannotGC nogc;
if (name->hasLatin1Chars())
DumpName(name->latin1Chars(nogc), name->length());
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 623379f61..7bfab87a3 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -19,6 +19,8 @@
#include "frontend/Parser.h"
+#include <new>
+
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
@@ -1451,16 +1453,26 @@ template <typename Scope>
static typename Scope::Data*
NewEmptyBindingData(ExclusiveContext* cx, LifoAlloc& alloc, uint32_t numBindings)
{
+ using Data = typename Scope::Data;
size_t allocSize = Scope::sizeOfData(numBindings);
- typename Scope::Data* bindings = static_cast<typename Scope::Data*>(alloc.alloc(allocSize));
- if (!bindings) {
+ auto* bindings = alloc.allocInSize<Data>(allocSize, numBindings);
+ if (!bindings)
ReportOutOfMemory(cx);
- return nullptr;
- }
- PodZero(bindings);
return bindings;
}
+/**
+ * Copy-construct |BindingName|s from |bindings| into |cursor|, then return
+ * the location one past the newly-constructed |BindingName|s.
+ */
+static MOZ_MUST_USE BindingName*
+FreshlyInitializeBindings(BindingName* cursor, const Vector<BindingName>& bindings)
+{
+ for (const BindingName& binding : bindings)
+ new (cursor++) BindingName(binding);
+ return cursor;
+}
+
template <>
Maybe<GlobalScope::Data*>
Parser<FullParseHandler>::newGlobalScopeData(ParseContext::Scope& scope)
@@ -1505,22 +1517,20 @@ Parser<FullParseHandler>::newGlobalScopeData(ParseContext::Scope& scope)
return Nothing();
// The ordering here is important. See comments in GlobalScope.
- BindingName* start = bindings->names;
+ BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
- PodCopy(cursor, funs.begin(), funs.length());
- cursor += funs.length();
+ cursor = FreshlyInitializeBindings(cursor, funs);
bindings->varStart = cursor - start;
- PodCopy(cursor, vars.begin(), vars.length());
- cursor += vars.length();
+ cursor = FreshlyInitializeBindings(cursor, vars);
bindings->letStart = cursor - start;
- PodCopy(cursor, lets.begin(), lets.length());
- cursor += lets.length();
+ cursor = FreshlyInitializeBindings(cursor, lets);
bindings->constStart = cursor - start;
- PodCopy(cursor, consts.begin(), consts.length());
+ cursor = FreshlyInitializeBindings(cursor, consts);
+
bindings->length = numBindings;
}
@@ -1572,22 +1582,20 @@ Parser<FullParseHandler>::newModuleScopeData(ParseContext::Scope& scope)
return Nothing();
// The ordering here is important. See comments in ModuleScope.
- BindingName* start = bindings->names;
+ BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
- PodCopy(cursor, imports.begin(), imports.length());
- cursor += imports.length();
+ cursor = FreshlyInitializeBindings(cursor, imports);
bindings->varStart = cursor - start;
- PodCopy(cursor, vars.begin(), vars.length());
- cursor += vars.length();
+ cursor = FreshlyInitializeBindings(cursor, vars);
bindings->letStart = cursor - start;
- PodCopy(cursor, lets.begin(), lets.length());
- cursor += lets.length();
+ cursor = FreshlyInitializeBindings(cursor, lets);
bindings->constStart = cursor - start;
- PodCopy(cursor, consts.begin(), consts.length());
+ cursor = FreshlyInitializeBindings(cursor, consts);
+
bindings->length = numBindings;
}
@@ -1623,16 +1631,16 @@ Parser<FullParseHandler>::newEvalScopeData(ParseContext::Scope& scope)
if (!bindings)
return Nothing();
- BindingName* start = bindings->names;
+ BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
// Keep track of what vars are functions. This is only used in BCE to omit
// superfluous DEFVARs.
- PodCopy(cursor, funs.begin(), funs.length());
- cursor += funs.length();
+ cursor = FreshlyInitializeBindings(cursor, funs);
bindings->varStart = cursor - start;
- PodCopy(cursor, vars.begin(), vars.length());
+ cursor = FreshlyInitializeBindings(cursor, vars);
+
bindings->length = numBindings;
}
@@ -1719,18 +1727,17 @@ Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool
return Nothing();
// The ordering here is important. See comments in FunctionScope.
- BindingName* start = bindings->names;
+ BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
- PodCopy(cursor, positionalFormals.begin(), positionalFormals.length());
- cursor += positionalFormals.length();
+ cursor = FreshlyInitializeBindings(cursor, positionalFormals);
bindings->nonPositionalFormalStart = cursor - start;
- PodCopy(cursor, formals.begin(), formals.length());
- cursor += formals.length();
+ cursor = FreshlyInitializeBindings(cursor, formals);
bindings->varStart = cursor - start;
- PodCopy(cursor, vars.begin(), vars.length());
+ cursor = FreshlyInitializeBindings(cursor, vars);
+
bindings->length = numBindings;
}
@@ -1760,10 +1767,11 @@ Parser<FullParseHandler>::newVarScopeData(ParseContext::Scope& scope)
return Nothing();
// The ordering here is important. See comments in FunctionScope.
- BindingName* start = bindings->names;
+ BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
- PodCopy(cursor, vars.begin(), vars.length());
+ cursor = FreshlyInitializeBindings(cursor, vars);
+
bindings->length = numBindings;
}
@@ -1808,14 +1816,14 @@ Parser<FullParseHandler>::newLexicalScopeData(ParseContext::Scope& scope)
return Nothing();
// The ordering here is important. See comments in LexicalScope.
- BindingName* cursor = bindings->names;
+ BindingName* cursor = bindings->trailingNames.start();
BindingName* start = cursor;
- PodCopy(cursor, lets.begin(), lets.length());
- cursor += lets.length();
+ cursor = FreshlyInitializeBindings(cursor, lets);
bindings->constStart = cursor - start;
- PodCopy(cursor, consts.begin(), consts.length());
+ cursor = FreshlyInitializeBindings(cursor, consts);
+
bindings->length = numBindings;
}
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index b2c105999..3ea4c9d29 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1231,34 +1231,34 @@ BindingIter::trace(JSTracer* trc)
void
LexicalScope::Data::trace(JSTracer* trc)
{
- TraceBindingNames(trc, names, length);
+ TraceBindingNames(trc, trailingNames.start(), length);
}
void
FunctionScope::Data::trace(JSTracer* trc)
{
TraceNullableEdge(trc, &canonicalFunction, "scope canonical function");
- TraceNullableBindingNames(trc, names, length);
+ TraceNullableBindingNames(trc, trailingNames.start(), length);
}
void
VarScope::Data::trace(JSTracer* trc)
{
- TraceBindingNames(trc, names, length);
+ TraceBindingNames(trc, trailingNames.start(), length);
}
void
GlobalScope::Data::trace(JSTracer* trc)
{
- TraceBindingNames(trc, names, length);
+ TraceBindingNames(trc, trailingNames.start(), length);
}
void
EvalScope::Data::trace(JSTracer* trc)
{
- TraceBindingNames(trc, names, length);
+ TraceBindingNames(trc, trailingNames.start(), length);
}
void
ModuleScope::Data::trace(JSTracer* trc)
{
TraceNullableEdge(trc, &module, "scope module");
- TraceBindingNames(trc, names, length);
+ TraceBindingNames(trc, trailingNames.start(), length);
}
void
Scope::traceChildren(JSTracer* trc)
@@ -1302,13 +1302,13 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
traverseEdge(scope, static_cast<Scope*>(scope->enclosing_));
if (scope->environmentShape_)
traverseEdge(scope, static_cast<Shape*>(scope->environmentShape_));
- BindingName* names = nullptr;
+ TrailingNamesArray* names = nullptr;
uint32_t length = 0;
switch (scope->kind_) {
case ScopeKind::Function: {
FunctionScope::Data* data = reinterpret_cast<FunctionScope::Data*>(scope->data_);
traverseEdge(scope, static_cast<JSObject*>(data->canonicalFunction));
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1316,7 +1316,7 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::FunctionBodyVar:
case ScopeKind::ParameterExpressionVar: {
VarScope::Data* data = reinterpret_cast<VarScope::Data*>(scope->data_);
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1327,7 +1327,7 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::NamedLambda:
case ScopeKind::StrictNamedLambda: {
LexicalScope::Data* data = reinterpret_cast<LexicalScope::Data*>(scope->data_);
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1335,7 +1335,7 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::Global:
case ScopeKind::NonSyntactic: {
GlobalScope::Data* data = reinterpret_cast<GlobalScope::Data*>(scope->data_);
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1343,7 +1343,7 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::Eval:
case ScopeKind::StrictEval: {
EvalScope::Data* data = reinterpret_cast<EvalScope::Data*>(scope->data_);
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1351,7 +1351,7 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::Module: {
ModuleScope::Data* data = reinterpret_cast<ModuleScope::Data*>(scope->data_);
traverseEdge(scope, static_cast<JSObject*>(data->module));
- names = data->names;
+ names = &data->trailingNames;
length = data->length;
break;
}
@@ -1361,12 +1361,12 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
}
if (scope->kind_ == ScopeKind::Function) {
for (uint32_t i = 0; i < length; i++) {
- if (JSAtom* name = names[i].name())
+ if (JSAtom* name = names->operator[](i).name())
traverseEdge(scope, static_cast<JSString*>(name));
}
} else {
for (uint32_t i = 0; i < length; i++)
- traverseEdge(scope, static_cast<JSString*>(names[i].name()));
+ traverseEdge(scope, static_cast<JSString*>(names->operator[](i).name()));
}
}
diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
index 112b34586..a71c03695 100644
--- a/js/src/vm/Scope.cpp
+++ b/js/src/vm/Scope.cpp
@@ -191,12 +191,12 @@ template <typename ConcreteScope>
static UniquePtr<typename ConcreteScope::Data>
NewEmptyScopeData(ExclusiveContext* cx, uint32_t length = 0)
{
- uint8_t* bytes = cx->zone()->pod_calloc<uint8_t>(ConcreteScope::sizeOfData(length));
+ uint8_t* bytes = cx->zone()->pod_malloc<uint8_t>(ConcreteScope::sizeOfData(length));
if (!bytes)
ReportOutOfMemory(cx);
auto data = reinterpret_cast<typename ConcreteScope::Data*>(bytes);
if (data)
- new (data) typename ConcreteScope::Data();
+ new (data) typename ConcreteScope::Data(length);
return UniquePtr<typename ConcreteScope::Data>(data);
}
@@ -273,7 +273,7 @@ Scope::XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
}
for (uint32_t i = 0; i < length; i++) {
- if (!XDRBindingName(xdr, &data->names[i])) {
+ if (!XDRBindingName(xdr, &data->trailingNames[i])) {
if (mode == XDR_DECODE) {
DeleteScopeData(data.get());
data.set(nullptr);
@@ -1250,7 +1250,7 @@ BindingIter::init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t fla
init(0, 0, 0, 0, 0, 0,
CanHaveEnvironmentSlots | flags,
firstFrameSlot, JSSLOT_FREE(&LexicalEnvironmentObject::class_),
- data.names, data.length);
+ data.trailingNames.start(), data.length);
} else {
// imports - [0, 0)
// positional formals - [0, 0)
@@ -1262,7 +1262,7 @@ BindingIter::init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t fla
init(0, 0, 0, 0, 0, data.constStart,
CanHaveFrameSlots | CanHaveEnvironmentSlots | flags,
firstFrameSlot, JSSLOT_FREE(&LexicalEnvironmentObject::class_),
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
}
@@ -1283,7 +1283,7 @@ BindingIter::init(FunctionScope::Data& data, uint8_t flags)
init(0, data.nonPositionalFormalStart, data.varStart, data.varStart, data.length, data.length,
flags,
0, JSSLOT_FREE(&CallObject::class_),
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
void
@@ -1299,7 +1299,7 @@ BindingIter::init(VarScope::Data& data, uint32_t firstFrameSlot)
init(0, 0, 0, 0, data.length, data.length,
CanHaveFrameSlots | CanHaveEnvironmentSlots,
firstFrameSlot, JSSLOT_FREE(&VarEnvironmentObject::class_),
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
void
@@ -1315,7 +1315,7 @@ BindingIter::init(GlobalScope::Data& data)
init(0, 0, 0, data.varStart, data.letStart, data.constStart,
CannotHaveSlots,
UINT32_MAX, UINT32_MAX,
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
void
@@ -1343,7 +1343,7 @@ BindingIter::init(EvalScope::Data& data, bool strict)
// consts - [data.length, data.length)
init(0, 0, 0, data.varStart, data.length, data.length,
flags, firstFrameSlot, firstEnvironmentSlot,
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
void
@@ -1359,7 +1359,7 @@ BindingIter::init(ModuleScope::Data& data)
init(data.varStart, data.varStart, data.varStart, data.varStart, data.letStart, data.constStart,
CanHaveFrameSlots | CanHaveEnvironmentSlots,
0, JSSLOT_FREE(&ModuleEnvironmentObject::class_),
- data.names, data.length);
+ data.trailingNames.start(), data.length);
}
PositionalFormalParameterIter::PositionalFormalParameterIter(JSScript* script)
diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
index 5304d6713..1d04fd9f6 100644
--- a/js/src/vm/Scope.h
+++ b/js/src/vm/Scope.h
@@ -12,6 +12,7 @@
#include "jsobj.h"
#include "jsopcode.h"
+#include "jsutil.h"
#include "gc/Heap.h"
#include "gc/Policy.h"
@@ -111,6 +112,47 @@ class BindingName
void trace(JSTracer* trc);
};
+/**
+ * The various {Global,Module,...}Scope::Data classes consist of always-present
+ * bits, then a trailing array of BindingNames. The various Data classes all
+ * end in a TrailingNamesArray that contains sized/aligned space for *one*
+ * BindingName. Data instances that contain N BindingNames, are then allocated
+ * in sizeof(Data) + (space for (N - 1) BindingNames). Because this class's
+ * |data_| field is properly sized/aligned, the N-BindingName array can start
+ * at |data_|.
+ *
+ * This is concededly a very low-level representation, but we want to only
+ * allocate once for data+bindings both, and this does so approximately as
+ * elegantly as C++ allows.
+ */
+class TrailingNamesArray
+{
+ private:
+ alignas(BindingName) unsigned char data_[sizeof(BindingName)];
+
+ private:
+ // Some versions of GCC treat it as a -Wstrict-aliasing violation (ergo a
+ // -Werror compile error) to reinterpret_cast<> |data_| to |T*|, even
+ // through |void*|. Placing the latter cast in these separate functions
+ // breaks the chain such that affected GCC versions no longer warn/error.
+ void* ptr() {
+ return data_;
+ }
+
+ public:
+ // Explicitly ensure no one accidentally allocates scope data without
+ // poisoning its trailing names.
+ TrailingNamesArray() = delete;
+
+ explicit TrailingNamesArray(size_t nameCount) {
+ if (nameCount)
+ JS_POISON(&data_, 0xCC, sizeof(BindingName) * nameCount);
+ }
+ BindingName* start() { return reinterpret_cast<BindingName*>(ptr()); }
+
+ BindingName& operator[](size_t i) { return start()[i]; }
+};
+
class BindingLocation
{
public:
@@ -337,16 +379,19 @@ class LexicalScope : public Scope
//
// lets - [0, constStart)
// consts - [constStart, length)
- uint32_t constStart;
- uint32_t length;
+ uint32_t constStart = 0;
+ uint32_t length = 0;
// Frame slots [0, nextFrameSlot) are live when this is the innermost
// scope.
- uint32_t nextFrameSlot;
+ uint32_t nextFrameSlot = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};
@@ -433,11 +478,11 @@ class FunctionScope : public Scope
// The canonical function of the scope, as during a scope walk we
// often query properties of the JSFunction (e.g., is the function an
// arrow).
- GCPtrFunction canonicalFunction;
+ GCPtrFunction canonicalFunction = {};
// If parameter expressions are present, parameters act like lexical
// bindings.
- bool hasParameterExprs;
+ bool hasParameterExprs = false;
// Bindings are sorted by kind in both frames and environments.
//
@@ -452,17 +497,20 @@ class FunctionScope : public Scope
// positional formals - [0, nonPositionalFormalStart)
// other formals - [nonPositionalParamStart, varStart)
// vars - [varStart, length)
- uint16_t nonPositionalFormalStart;
- uint16_t varStart;
- uint32_t length;
+ uint16_t nonPositionalFormalStart = 0;
+ uint16_t varStart = 0;
+ uint32_t length = 0;
// Frame slots [0, nextFrameSlot) are live when this is the innermost
// scope.
- uint32_t nextFrameSlot;
+ uint32_t nextFrameSlot = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};
@@ -548,15 +596,18 @@ class VarScope : public Scope
struct Data
{
// All bindings are vars.
- uint32_t length;
+ uint32_t length = 0;
// Frame slots [firstFrameSlot(), nextFrameSlot) are live when this is
// the innermost scope.
- uint32_t nextFrameSlot;
+ uint32_t nextFrameSlot = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};
@@ -638,14 +689,17 @@ class GlobalScope : public Scope
// vars - [varStart, letStart)
// lets - [letStart, constStart)
// consts - [constStart, length)
- uint32_t varStart;
- uint32_t letStart;
- uint32_t constStart;
- uint32_t length;
+ uint32_t varStart = 0;
+ uint32_t letStart = 0;
+ uint32_t constStart = 0;
+ uint32_t length = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};
@@ -736,16 +790,19 @@ class EvalScope : public Scope
//
// top-level funcs - [0, varStart)
// vars - [varStart, length)
- uint32_t varStart;
- uint32_t length;
+ uint32_t varStart = 0;
+ uint32_t length = 0;
// Frame slots [0, nextFrameSlot) are live when this is the innermost
// scope.
- uint32_t nextFrameSlot;
+ uint32_t nextFrameSlot = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};
@@ -827,7 +884,7 @@ class ModuleScope : public Scope
struct Data
{
// The module of the scope.
- GCPtr<ModuleObject*> module;
+ GCPtr<ModuleObject*> module = {};
// Bindings are sorted by kind.
//
@@ -835,18 +892,21 @@ class ModuleScope : public Scope
// vars - [varStart, letStart)
// lets - [letStart, constStart)
// consts - [constStart, length)
- uint32_t varStart;
- uint32_t letStart;
- uint32_t constStart;
- uint32_t length;
+ uint32_t varStart = 0;
+ uint32_t letStart = 0;
+ uint32_t constStart = 0;
+ uint32_t length = 0;
// Frame slots [0, nextFrameSlot) are live when this is the innermost
// scope.
- uint32_t nextFrameSlot;
+ uint32_t nextFrameSlot = 0;
// The array of tagged JSAtom* names, allocated beyond the end of the
// struct.
- BindingName names[1];
+ TrailingNamesArray trailingNames;
+
+ explicit Data(size_t nameCount) : trailingNames(nameCount) {}
+ Data() = delete;
void trace(JSTracer* trc);
};