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.

This commit is contained in:
trav90 2018-09-02 18:59:51 -05:00 • committed by Roy Tam
commit 78d0ec7fc9
4 changed files with 72 additions and 31 deletions

View file

@ -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);
}

View file

@ -12,6 +12,7 @@
#include "jsobj.h"
#include "jsopcode.h"
#include "jsutil.h"
#include "gc/Heap.h"
#include "gc/Policy.h"
@ -139,6 +140,14 @@ 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);
}
BindingName* start() { return reinterpret_cast<BindingName*>(ptr()); }
BindingName& operator[](size_t i) { return start()[i]; }
@ -370,17 +379,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);
};
@ -466,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.
//
@ -485,18 +497,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);
};
@ -581,16 +596,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);
};
@ -671,15 +689,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);
};
@ -769,17 +790,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);
};
@ -860,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.
//
@ -868,19 +892,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);
};