Bug 1181869 - Update Bindings to use normal Rooted primitives; r=shu

This commit is contained in:
Terrence Cole 2015-07-09 13:34:50 -07:00
Родитель 59382657f2
Коммит a9e6bc1d23
9 изменённых файлов: 191 добавлений и 91 удалений

Просмотреть файл

@ -448,12 +448,13 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
// scope dynamically via JSOP_DEFFUN/VAR). They may have block-scoped
// locals, however, which are allocated to the fixed part of the stack
// frame.
InternalHandle<Bindings*> bindings(script, &script->bindings);
if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, 0,
Rooted<Bindings> bindings(cx, script->bindings);
if (!Bindings::initWithTemporaryStorage(cx, &bindings, 0, 0, 0,
pc->blockScopeDepth, 0, 0, nullptr))
{
return nullptr;
}
script->bindings = bindings;
if (!JSScript::fullyInitFromEmitter(cx, script, &bce))
return nullptr;

Просмотреть файл

@ -3414,8 +3414,7 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
switchToPrologue();
if (!emit1(JSOP_ARGUMENTS))
return false;
InternalBindingsHandle bindings(script, &script->bindings);
BindingIter bi = Bindings::argumentsBinding(cx, bindings);
BindingIter bi = Bindings::argumentsBinding(cx, script);
if (script->bindingIsAliased(bi)) {
ScopeCoordinate sc;
sc.setHops(0);

Просмотреть файл

@ -371,7 +371,7 @@ template <typename ParseHandler>
bool
ParseContext<ParseHandler>::generateFunctionBindings(ExclusiveContext* cx, TokenStream& ts,
LifoAlloc& alloc,
InternalHandle<Bindings*> bindings) const
MutableHandle<Bindings> bindings) const
{
MOZ_ASSERT(sc->isFunctionBox());
MOZ_ASSERT(args_.length() < ARGNO_LIMIT);
@ -847,10 +847,10 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
}
}
InternalHandle<Bindings*> funboxBindings =
InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
if (!funpc.generateFunctionBindings(context, tokenStream, alloc, funboxBindings))
Rooted<Bindings> bindings(context, funbox->bindings);
if (!funpc.generateFunctionBindings(context, tokenStream, alloc, &bindings))
return null();
funbox->bindings = bindings;
return fn;
}
@ -1470,9 +1470,12 @@ Parser<FullParseHandler>::leaveFunction(ParseNode* fn, ParseContext<FullParseHan
}
}
InternalHandle<Bindings*> bindings =
InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
return pc->generateFunctionBindings(context, tokenStream, alloc, bindings);
Rooted<Bindings> bindings(context, funbox->bindings);
if (!pc->generateFunctionBindings(context, tokenStream, alloc, &bindings))
return false;
funbox->bindings = bindings;
return true;
}
template <>
@ -2492,10 +2495,10 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned st
}
}
InternalHandle<Bindings*> bindings =
InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
if (!pc->generateFunctionBindings(context, tokenStream, alloc, bindings))
Rooted<Bindings> bindings(context, funbox->bindings);
if (!pc->generateFunctionBindings(context, tokenStream, alloc, &bindings))
return null();
funbox->bindings = bindings;
if (!FoldConstants(context, &pn, this))
return null();

Просмотреть файл

@ -213,7 +213,7 @@ struct ParseContext : public GenericParseContext
*/
bool generateFunctionBindings(ExclusiveContext* cx, TokenStream& ts,
LifoAlloc& alloc,
InternalHandle<Bindings*> bindings) const;
MutableHandle<Bindings> bindings) const;
private:
ParseContext** parserPC; /* this points to the Parser's active pc

Просмотреть файл

@ -44,12 +44,6 @@ typedef RootedValueMap::Enum RootEnum;
// GCC 4.4, since it requires template function parameters to have external
// linkage.
void
MarkBindingsRoot(JSTracer* trc, Bindings* bindings, const char* name)
{
bindings->trace(trc);
}
void
MarkPropertyDescriptorRoot(JSTracer* trc, JSPropertyDescriptor* pd, const char* name)
{
@ -87,7 +81,6 @@ MarkExactStackRootsAcrossTypes(T context, JSTracer* trc)
MarkExactStackRootList<LazyScript*>(trc, context, "exact-lazy-script");
MarkExactStackRootList<jsid>(trc, context, "exact-id");
MarkExactStackRootList<Value>(trc, context, "exact-value");
MarkExactStackRootList<Bindings, MarkBindingsRoot>(trc, context, "Bindings");
MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
trc, context, "JSPropertyDescriptor");
MarkExactStackRootList<JS::StaticTraceable,

Просмотреть файл

@ -325,7 +325,6 @@ enum ThingRootKind
THING_ROOT_LAZY_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_BINDINGS,
THING_ROOT_PROPERTY_DESCRIPTOR,
THING_ROOT_PROP_DESC,
THING_ROOT_STATIC_TRACEABLE,

Просмотреть файл

@ -61,24 +61,25 @@ using mozilla::PodZero;
using mozilla::RotateLeft;
/* static */ BindingIter
Bindings::argumentsBinding(ExclusiveContext* cx, InternalBindingsHandle bindings)
Bindings::argumentsBinding(ExclusiveContext* cx, HandleScript script)
{
HandlePropertyName arguments = cx->names().arguments;
BindingIter bi(bindings);
BindingIter bi(script);
while (bi->name() != arguments)
bi++;
return bi;
}
bool
Bindings::initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle self,
Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle<Bindings> self,
uint32_t numArgs, uint32_t numVars,
uint32_t numBodyLevelLexicals, uint32_t numBlockScoped,
uint32_t numUnaliasedVars, uint32_t numUnaliasedBodyLevelLexicals,
Binding* bindingArray)
const Binding* bindingArray)
{
MOZ_ASSERT(!self->callObjShape_);
MOZ_ASSERT(self->bindingArrayAndFlag_ == TEMPORARY_STORAGE_BIT);
MOZ_ASSERT(!self.callObjShape());
MOZ_ASSERT(self.bindingArrayUsingTemporaryStorage());
MOZ_ASSERT(!self.bindingArray());
MOZ_ASSERT(!(uintptr_t(bindingArray) & TEMPORARY_STORAGE_BIT));
MOZ_ASSERT(numArgs <= ARGC_LIMIT);
MOZ_ASSERT(numVars <= LOCALNO_LIMIT);
@ -93,13 +94,13 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle
MOZ_ASSERT(numUnaliasedVars <= numVars);
MOZ_ASSERT(numUnaliasedBodyLevelLexicals <= numBodyLevelLexicals);
self->bindingArrayAndFlag_ = uintptr_t(bindingArray) | TEMPORARY_STORAGE_BIT;
self->numArgs_ = numArgs;
self->numVars_ = numVars;
self->numBodyLevelLexicals_ = numBodyLevelLexicals;
self->numBlockScoped_ = numBlockScoped;
self->numUnaliasedVars_ = numUnaliasedVars;
self->numUnaliasedBodyLevelLexicals_ = numUnaliasedBodyLevelLexicals;
self.setBindingArray(bindingArray, TEMPORARY_STORAGE_BIT);
self.setNumArgs(numArgs);
self.setNumVars(numVars);
self.setNumBodyLevelLexicals(numBodyLevelLexicals);
self.setNumBlockScoped(numBlockScoped);
self.setNumUnaliasedVars(numUnaliasedVars);
self.setNumUnaliasedBodyLevelLexicals(numUnaliasedBodyLevelLexicals);
// Get the initial shape to use when creating CallObjects for this script.
// After creation, a CallObject's shape may change completely (via direct eval() or
@ -134,7 +135,7 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle
nslots++;
}
}
self->aliasedBodyLevelLexicalBegin_ = aliasedBodyLevelLexicalBegin;
self.setAliasedBodyLevelLexicalBegin(aliasedBodyLevelLexicalBegin);
// Put as many of nslots inline into the object header as possible.
uint32_t nfixed = gc::GetGCKindSlots(gc::GetGCObjectKind(nslots));
@ -190,7 +191,7 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle
MOZ_ASSERT(slot == nslots);
MOZ_ASSERT(!shape->inDictionary());
self->callObjShape_.init(shape);
self.setCallObjShape(shape);
return true;
}
@ -218,12 +219,12 @@ Bindings::switchToScriptStorage(Binding* newBindingArray)
return reinterpret_cast<uint8_t*>(newBindingArray + count());
}
bool
Bindings::clone(JSContext* cx, InternalBindingsHandle self,
/* static */ bool
Bindings::clone(JSContext* cx, MutableHandle<Bindings> self,
uint8_t* dstScriptData, HandleScript srcScript)
{
/* The clone has the same bindingArray_ offset as 'src'. */
Bindings& src = srcScript->bindings;
Handle<Bindings> src = Handle<Bindings>::fromMarkedLocation(&srcScript->bindings);
ptrdiff_t off = (uint8_t*)src.bindingArray() - srcScript->data;
MOZ_ASSERT(off >= 0);
MOZ_ASSERT(size_t(off) <= srcScript->dataSize());
@ -243,16 +244,10 @@ Bindings::clone(JSContext* cx, InternalBindingsHandle self,
return false;
}
self->switchToScriptStorage(dstPackedBindings);
self.switchToScriptStorage(dstPackedBindings);
return true;
}
/* static */ Bindings
GCMethods<Bindings>::initial()
{
return Bindings();
}
template<XDRMode mode>
static bool
XDRScriptBindings(XDRState<mode>* xdr, LifoAllocScope& las, uint16_t numArgs, uint32_t numVars,
@ -302,14 +297,15 @@ XDRScriptBindings(XDRState<mode>* xdr, LifoAllocScope& las, uint16_t numArgs, ui
bindingArray[i] = Binding(name, kind, aliased);
}
InternalBindingsHandle bindings(script, &script->bindings);
if (!Bindings::initWithTemporaryStorage(cx, bindings, numArgs, numVars,
Rooted<Bindings> bindings(cx, script->bindings);
if (!Bindings::initWithTemporaryStorage(cx, &bindings, numArgs, numVars,
numBodyLevelLexicals, numBlockScoped,
numUnaliasedVars, numUnaliasedBodyLevelLexicals,
bindingArray))
{
return false;
}
script->bindings = bindings;
}
return true;
@ -3125,9 +3121,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
/* Bindings */
Rooted<Bindings> bindings(cx);
InternalHandle<Bindings*> bindingsHandle =
InternalHandle<Bindings*>::fromMarkedLocation(bindings.address());
if (!Bindings::clone(cx, bindingsHandle, data, src))
if (!Bindings::clone(cx, &bindings, data, src))
return false;
/* Objects */
@ -3712,8 +3706,7 @@ js::SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame,
* object. Note that 'arguments' may have already been overwritten.
*/
InternalBindingsHandle bindings(script, &script->bindings);
BindingIter bi = Bindings::argumentsBinding(cx, bindings);
BindingIter bi = Bindings::argumentsBinding(cx, script);
if (script->bindingIsAliased(bi)) {
/*

Просмотреть файл

@ -200,19 +200,18 @@ class Binding
JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t));
class Bindings;
typedef InternalHandle<Bindings*> InternalBindingsHandle;
/*
* Formal parameters and local variables are stored in a shape tree
* path encapsulated within this class. This class represents bindings for
* both function and top-level scripts (the latter is needed to track names in
* strict mode eval code, to give such code its own lexical environment).
*/
class Bindings
class Bindings : public JS::StaticTraceable
{
friend class BindingIter;
friend class AliasedFormalIter;
template <typename Outer> friend class BindingsOperations;
template <typename Outer> friend class MutableBindingsOperations;
RelocatablePtrShape callObjShape_;
uintptr_t bindingArrayAndFlag_;
@ -250,7 +249,12 @@ class Bindings
return reinterpret_cast<Binding*>(bindingArrayAndFlag_ & ~TEMPORARY_STORAGE_BIT);
}
inline Bindings();
Bindings()
: callObjShape_(nullptr), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT),
numArgs_(0), numBlockScoped_(0),
numBodyLevelLexicals_(0), numUnaliasedBodyLevelLexicals_(0),
numVars_(0), numUnaliasedVars_(0)
{}
/*
* Initialize a Bindings with a pointer into temporary storage.
@ -259,11 +263,14 @@ class Bindings
* switchToScriptStorage must be called, providing a pointer into the
* Binding array stored in script->data.
*/
static bool initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle self,
uint32_t numArgs, uint32_t numVars,
uint32_t numBodyLevelLexicals, uint32_t numBlockScoped,
uint32_t numUnaliasedVars, uint32_t numUnaliasedBodyLevelLexicals,
Binding* bindingArray);
static bool initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle<Bindings> self,
uint32_t numArgs,
uint32_t numVars,
uint32_t numBodyLevelLexicals,
uint32_t numBlockScoped,
uint32_t numUnaliasedVars,
uint32_t numUnaliasedBodyLevelLexicals,
const Binding* bindingArray);
// Initialize a trivial Bindings with no slots and an empty callObjShape.
bool initTrivial(ExclusiveContext* cx);
@ -292,7 +299,7 @@ class Bindings
* Clone srcScript's bindings (as part of js::CloneScript). dstScriptData
* is the pointer to what will eventually be dstScript->data.
*/
static bool clone(JSContext* cx, InternalBindingsHandle self, uint8_t* dstScriptData,
static bool clone(JSContext* cx, MutableHandle<Bindings> self, uint8_t* dstScriptData,
HandleScript srcScript);
uint32_t numArgs() const { return numArgs_; }
@ -317,7 +324,7 @@ class Bindings
Shape* callObjShape() const { return callObjShape_; }
/* Convenience method to get the var index of 'arguments'. */
static BindingIter argumentsBinding(ExclusiveContext* cx, InternalBindingsHandle);
static BindingIter argumentsBinding(ExclusiveContext* cx, HandleScript script);
/* Return whether the binding at bindingIndex is aliased. */
bool bindingIsAliased(uint32_t bindingIndex);
@ -333,13 +340,122 @@ class Bindings
Binding* begin() const { return bindingArray(); }
Binding* end() const { return bindingArray() + count(); }
static js::ThingRootKind rootKind() { return js::THING_ROOT_BINDINGS; }
static void trace(Bindings* self, JSTracer* trc) { self->trace(trc); }
void trace(JSTracer* trc);
};
template <class Outer>
class BindingsOperations
{
const Bindings& bindings() const { return static_cast<const Outer*>(this)->extract(); }
public:
// Direct data access to the underlying bindings.
const RelocatablePtrShape& callObjShape() const {
return bindings().callObjShape_;
}
uint16_t numArgs() const {
return bindings().numArgs_;
}
uint16_t numBlockScoped() const {
return bindings().numBlockScoped_;
}
uint16_t numBodyLevelLexicals() const {
return bindings().numBodyLevelLexicals_;
}
uint16_t aliasedBodyLevelLexicalBegin() const {
return bindings().aliasedBodyLevelLexicalBegin_;
}
uint16_t numUnaliasedBodyLevelLexicals() const {
return bindings().numUnaliasedBodyLevelLexicals_;
}
uint32_t numVars() const {
return bindings().numVars_;
}
uint32_t numUnaliasedVars() const {
return bindings().numUnaliasedVars_;
}
// Binding array access.
bool bindingArrayUsingTemporaryStorage() const {
return bindings().bindingArrayUsingTemporaryStorage();
}
const Binding* bindingArray() const {
return bindings().bindingArray();
}
uint32_t count() const {
return bindings().count();
}
// Helpers.
uint32_t numBodyLevelLocals() const {
return numVars() + numBodyLevelLexicals();
}
uint32_t numUnaliasedBodyLevelLocals() const {
return numUnaliasedVars() + numUnaliasedBodyLevelLexicals();
}
uint32_t numAliasedBodyLevelLocals() const {
return numBodyLevelLocals() - numUnaliasedBodyLevelLocals();
}
uint32_t numLocals() const {
return numVars() + numBodyLevelLexicals() + numBlockScoped();
}
uint32_t numFixedLocals() const {
return numUnaliasedVars() + numUnaliasedBodyLevelLexicals() + numBlockScoped();
}
uint32_t lexicalBegin() const {
return numArgs() + numVars();
}
};
template <class Outer>
class MutableBindingsOperations : public BindingsOperations<Outer>
{
Bindings& bindings() { return static_cast<Outer*>(this)->extractMutable(); }
public:
void setCallObjShape(HandleShape shape) { bindings().callObjShape_ = shape; }
void setBindingArray(const Binding* bindingArray, uintptr_t temporaryBit) {
bindings().bindingArrayAndFlag_ = uintptr_t(bindingArray) | temporaryBit;
}
void setNumArgs(uint16_t num) { bindings().numArgs_ = num; }
void setNumVars(uint32_t num) { bindings().numVars_ = num; }
void setNumBodyLevelLexicals(uint16_t num) { bindings().numBodyLevelLexicals_ = num; }
void setNumBlockScoped(uint16_t num) { bindings().numBlockScoped_ = num; }
void setNumUnaliasedVars(uint32_t num) { bindings().numUnaliasedVars_ = num; }
void setNumUnaliasedBodyLevelLexicals(uint16_t num) {
bindings().numUnaliasedBodyLevelLexicals_ = num;
}
void setAliasedBodyLevelLexicalBegin(uint16_t offset) {
bindings().aliasedBodyLevelLexicalBegin_ = offset;
}
uint8_t* switchToScriptStorage(Binding* permanentStorage) {
return bindings().switchToScriptStorage(permanentStorage);
}
};
template <>
struct GCMethods<Bindings> {
static Bindings initial();
class HandleBase<Bindings> : public BindingsOperations<JS::Handle<Bindings>>
{
friend class BindingsOperations<JS::Handle<Bindings>>;
const Bindings& extract() const {
return static_cast<const JS::Handle<Bindings>*>(this)->get();
}
};
template <>
class MutableHandleBase<Bindings>
: public MutableBindingsOperations<JS::MutableHandle<Bindings>>
{
friend class BindingsOperations<JS::MutableHandle<Bindings>>;
const Bindings& extract() const {
return static_cast<const JS::MutableHandle<Bindings>*>(this)->get();
}
friend class MutableBindingsOperations<JS::MutableHandle<Bindings>>;
Bindings& extractMutable() {
return static_cast<JS::MutableHandle<Bindings>*>(this)->get();
}
};
class ScriptCounts
@ -1782,7 +1898,7 @@ namespace js {
*/
class BindingIter
{
const InternalBindingsHandle bindings_;
Handle<Bindings> bindings_;
uint32_t i_;
uint32_t unaliasedLocal_;
@ -1790,12 +1906,16 @@ class BindingIter
friend class Bindings;
public:
explicit BindingIter(const InternalBindingsHandle& bindings)
: bindings_(bindings), i_(0), unaliasedLocal_(0) {}
explicit BindingIter(const HandleScript& script)
: bindings_(script, &script->bindings), i_(0), unaliasedLocal_(0) {}
explicit BindingIter(Handle<Bindings> bindings)
: bindings_(bindings), i_(0), unaliasedLocal_(0)
{}
bool done() const { return i_ == bindings_->count(); }
explicit BindingIter(const HandleScript& script)
: bindings_(Handle<Bindings>::fromMarkedLocation(&script->bindings)),
i_(0), unaliasedLocal_(0)
{}
bool done() const { return i_ == bindings_.count(); }
explicit operator bool() const { return !done(); }
BindingIter& operator++() { (*this)++; return *this; }
@ -1813,7 +1933,7 @@ class BindingIter
// has no stack slot.
uint32_t frameIndex() const {
MOZ_ASSERT(!done());
if (i_ < bindings_->numArgs())
if (i_ < bindings_.numArgs())
return i_;
MOZ_ASSERT(!(*this)->aliased());
return unaliasedLocal_;
@ -1824,17 +1944,17 @@ class BindingIter
// both unaliased and aliased arguments.
uint32_t argIndex() const {
MOZ_ASSERT(!done());
MOZ_ASSERT(i_ < bindings_->numArgs());
MOZ_ASSERT(i_ < bindings_.numArgs());
return i_;
}
uint32_t argOrLocalIndex() const {
MOZ_ASSERT(!done());
return i_ < bindings_->numArgs() ? i_ : i_ - bindings_->numArgs();
return i_ < bindings_.numArgs() ? i_ : i_ - bindings_.numArgs();
}
uint32_t localIndex() const {
MOZ_ASSERT(!done());
MOZ_ASSERT(i_ >= bindings_->numArgs());
return i_ - bindings_->numArgs();
MOZ_ASSERT(i_ >= bindings_.numArgs());
return i_ - bindings_.numArgs();
}
bool isBodyLevelLexical() const {
MOZ_ASSERT(!done());
@ -1842,8 +1962,8 @@ class BindingIter
return binding.kind() != Binding::ARGUMENT;
}
const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_->bindingArray()[i_]; }
const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_->bindingArray()[i_]; }
const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_.bindingArray()[i_]; }
const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_.bindingArray()[i_]; }
};
/*

Просмотреть файл

@ -20,14 +20,6 @@
namespace js {
inline
Bindings::Bindings()
: callObjShape_(nullptr), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT),
numArgs_(0), numBlockScoped_(0),
numBodyLevelLexicals_(0), numUnaliasedBodyLevelLexicals_(0),
numVars_(0), numUnaliasedVars_(0)
{}
inline
AliasedFormalIter::AliasedFormalIter(JSScript* script)
: begin_(script->bindingArray()),