зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1461821 - Call the relevant scope-data constructor when allocating it, and poison/mark as undefined the memory for the trailing array of BindingNames, ratther than impermissibly PodZero-ing non-trivial classes willy-nilly. r=jandem
This commit is contained in:
Родитель
912e0bddf0
Коммит
7e808a56db
|
@ -16,6 +16,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
|
||||
|
@ -593,6 +595,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;
|
||||
|
|
|
@ -1762,13 +1762,11 @@ template <typename Scope>
|
|||
typename Scope::Data*
|
||||
NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, uint32_t numBindings)
|
||||
{
|
||||
using Data = typename Scope::Data;
|
||||
size_t allocSize = Scope::sizeOfData(numBindings);
|
||||
auto* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -204,12 +204,12 @@ template <typename ConcreteScope>
|
|||
static UniquePtr<typename ConcreteScope::Data>
|
||||
NewEmptyScopeData(JSContext* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include "jsutil.h"
|
||||
|
||||
#include "gc/DeletePolicy.h"
|
||||
#include "gc/Heap.h"
|
||||
#include "gc/Policy.h"
|
||||
|
@ -157,6 +159,15 @@ class TrailingNamesArray
|
|||
}
|
||||
|
||||
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, MemCheckKind::MakeUndefined);
|
||||
}
|
||||
|
||||
BindingName* start() { return reinterpret_cast<BindingName*>(ptr()); }
|
||||
|
||||
BindingName& operator[](size_t i) { return start()[i]; }
|
||||
|
@ -412,17 +423,20 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -514,11 +528,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.
|
||||
//
|
||||
|
@ -533,18 +547,21 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
Zone* zone() const;
|
||||
};
|
||||
|
@ -637,16 +654,19 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -732,15 +752,18 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -835,17 +858,20 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -931,7 +957,7 @@ class ModuleScope : public Scope
|
|||
struct Data
|
||||
{
|
||||
// The module of the scope.
|
||||
GCPtr<ModuleObject*> module;
|
||||
GCPtr<ModuleObject*> module = {};
|
||||
|
||||
// Bindings are sorted by kind.
|
||||
//
|
||||
|
@ -939,19 +965,22 @@ 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.
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
Zone* zone() const;
|
||||
};
|
||||
|
@ -1003,16 +1032,19 @@ class WasmInstanceScope : public Scope
|
|||
public:
|
||||
struct Data
|
||||
{
|
||||
uint32_t memoriesStart;
|
||||
uint32_t globalsStart;
|
||||
uint32_t length;
|
||||
uint32_t nextFrameSlot;
|
||||
uint32_t memoriesStart = 0;
|
||||
uint32_t globalsStart = 0;
|
||||
uint32_t length = 0;
|
||||
uint32_t nextFrameSlot = 0;
|
||||
|
||||
// The wasm instance of the scope.
|
||||
GCPtr<WasmInstanceObject*> instance;
|
||||
GCPtr<WasmInstanceObject*> instance = {};
|
||||
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
@ -1063,12 +1095,15 @@ class WasmFunctionScope : public Scope
|
|||
public:
|
||||
struct Data
|
||||
{
|
||||
uint32_t length;
|
||||
uint32_t nextFrameSlot;
|
||||
uint32_t funcIndex;
|
||||
uint32_t length = 0;
|
||||
uint32_t nextFrameSlot = 0;
|
||||
uint32_t funcIndex = 0;
|
||||
|
||||
TrailingNamesArray trailingNames;
|
||||
|
||||
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
|
||||
Data() = delete;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче