mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 10:15:41 +00:00
Bug 851627 - Make LifoAlloc::release run in O(1) (r=sstangl)
This commit is contained in:
parent
a5cff84c9d
commit
971d6ebe6e
@ -307,31 +307,30 @@ class LifoAlloc
|
|||||||
return static_cast<T *>(alloc(sizeof(T) * count));
|
return static_cast<T *>(alloc(sizeof(T) * count));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mark() {
|
class Mark {
|
||||||
markCount++;
|
BumpChunk *chunk;
|
||||||
|
void *markInChunk;
|
||||||
|
friend class LifoAlloc;
|
||||||
|
Mark(BumpChunk *chunk, void *markInChunk) : chunk(chunk), markInChunk(markInChunk) {}
|
||||||
|
public:
|
||||||
|
Mark() : chunk(NULL), markInChunk(NULL) {}
|
||||||
|
};
|
||||||
|
|
||||||
return latest ? latest->mark() : NULL;
|
Mark mark() {
|
||||||
|
markCount++;
|
||||||
|
return latest ? Mark(latest, latest->mark()) : Mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
void release(void *mark) {
|
void release(Mark mark) {
|
||||||
markCount--;
|
markCount--;
|
||||||
|
if (!mark.chunk) {
|
||||||
if (!mark) {
|
|
||||||
latest = first;
|
latest = first;
|
||||||
if (latest)
|
if (latest)
|
||||||
latest->resetBump();
|
latest->resetBump();
|
||||||
return;
|
} else {
|
||||||
|
latest = mark.chunk;
|
||||||
|
latest->release(mark.markInChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the chunk that contains |mark|, and make sure we don't pass
|
|
||||||
// |latest| along the way -- we should be making the chain of active
|
|
||||||
// chunks shorter, not longer!
|
|
||||||
BumpChunk *container;
|
|
||||||
for (container = first; !container->contains(mark); container = container->next())
|
|
||||||
JS_ASSERT(container != latest);
|
|
||||||
|
|
||||||
latest = container;
|
|
||||||
latest->release(mark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void releaseAll() {
|
void releaseAll() {
|
||||||
@ -381,18 +380,19 @@ class LifoAlloc
|
|||||||
|
|
||||||
class LifoAllocScope
|
class LifoAllocScope
|
||||||
{
|
{
|
||||||
LifoAlloc *lifoAlloc;
|
LifoAlloc *lifoAlloc;
|
||||||
void *mark;
|
LifoAlloc::Mark mark;
|
||||||
bool shouldRelease;
|
bool shouldRelease;
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LifoAllocScope(LifoAlloc *lifoAlloc
|
explicit LifoAllocScope(LifoAlloc *lifoAlloc
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
: lifoAlloc(lifoAlloc), shouldRelease(true)
|
: lifoAlloc(lifoAlloc),
|
||||||
|
mark(lifoAlloc->mark()),
|
||||||
|
shouldRelease(true)
|
||||||
{
|
{
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
mark = lifoAlloc->mark();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~LifoAllocScope() {
|
~LifoAllocScope() {
|
||||||
|
@ -384,7 +384,6 @@ Parser<ParseHandler>::Parser(JSContext *cx, const CompileOptions &options,
|
|||||||
: AutoGCRooter(cx, PARSER),
|
: AutoGCRooter(cx, PARSER),
|
||||||
context(cx),
|
context(cx),
|
||||||
tokenStream(cx, options, chars, length, thisForCtor()),
|
tokenStream(cx, options, chars, length, thisForCtor()),
|
||||||
tempPoolMark(NULL),
|
|
||||||
traceListHead(NULL),
|
traceListHead(NULL),
|
||||||
pc(NULL),
|
pc(NULL),
|
||||||
sct(NULL),
|
sct(NULL),
|
||||||
|
@ -263,7 +263,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
|
|||||||
{
|
{
|
||||||
JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
|
JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
|
||||||
TokenStream tokenStream;
|
TokenStream tokenStream;
|
||||||
void *tempPoolMark; /* initial JSContext.tempLifoAlloc mark */
|
LifoAlloc::Mark tempPoolMark;
|
||||||
|
|
||||||
/* list of parsed objects for GC tracing */
|
/* list of parsed objects for GC tracing */
|
||||||
ObjectBox *traceListHead;
|
ObjectBox *traceListHead;
|
||||||
|
@ -20,34 +20,27 @@ namespace ion {
|
|||||||
|
|
||||||
class TempAllocator
|
class TempAllocator
|
||||||
{
|
{
|
||||||
LifoAlloc *lifoAlloc_;
|
LifoAllocScope lifoScope_;
|
||||||
void *mark_;
|
|
||||||
|
|
||||||
// Linked list of GCThings rooted by this allocator.
|
// Linked list of GCThings rooted by this allocator.
|
||||||
CompilerRootNode *rootList_;
|
CompilerRootNode *rootList_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TempAllocator(LifoAlloc *lifoAlloc)
|
TempAllocator(LifoAlloc *lifoAlloc)
|
||||||
: lifoAlloc_(lifoAlloc),
|
: lifoScope_(lifoAlloc),
|
||||||
mark_(lifoAlloc->mark()),
|
|
||||||
rootList_(NULL)
|
rootList_(NULL)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~TempAllocator()
|
|
||||||
{
|
|
||||||
lifoAlloc_->release(mark_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *allocateInfallible(size_t bytes)
|
void *allocateInfallible(size_t bytes)
|
||||||
{
|
{
|
||||||
void *p = lifoAlloc_->allocInfallible(bytes);
|
void *p = lifoScope_.alloc().allocInfallible(bytes);
|
||||||
JS_ASSERT(p);
|
JS_ASSERT(p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *allocate(size_t bytes)
|
void *allocate(size_t bytes)
|
||||||
{
|
{
|
||||||
void *p = lifoAlloc_->alloc(bytes);
|
void *p = lifoScope_.alloc().alloc(bytes);
|
||||||
if (!ensureBallast())
|
if (!ensureBallast())
|
||||||
return NULL;
|
return NULL;
|
||||||
return p;
|
return p;
|
||||||
@ -55,7 +48,7 @@ class TempAllocator
|
|||||||
|
|
||||||
LifoAlloc *lifoAlloc()
|
LifoAlloc *lifoAlloc()
|
||||||
{
|
{
|
||||||
return lifoAlloc_;
|
return &lifoScope_.alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilerRootNode *&rootList()
|
CompilerRootNode *&rootList()
|
||||||
@ -66,7 +59,7 @@ class TempAllocator
|
|||||||
bool ensureBallast() {
|
bool ensureBallast() {
|
||||||
// Most infallible Ion allocations are small, so we use a ballast of
|
// Most infallible Ion allocations are small, so we use a ballast of
|
||||||
// ~16K for now.
|
// ~16K for now.
|
||||||
return lifoAlloc_->ensureUnusedApproximate(16 * 1024);
|
return lifoScope_.alloc().ensureUnusedApproximate(16 * 1024);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -475,22 +475,27 @@ JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern JS_PUBLIC_API(uintptr_t *)
|
extern JS_PUBLIC_API(uintptr_t *)
|
||||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **memp)
|
||||||
{
|
{
|
||||||
RootedScript script(cx, fun->nonLazyScript());
|
RootedScript script(cx, fun->nonLazyScript());
|
||||||
BindingVector bindings(cx);
|
BindingVector bindings(cx);
|
||||||
if (!FillBindingVector(script, &bindings))
|
if (!FillBindingVector(script, &bindings))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Munge data into the API this method implements. Avert your eyes! */
|
LifoAlloc &lifo = cx->tempLifoAlloc();
|
||||||
*markp = cx->tempLifoAlloc().mark();
|
|
||||||
|
|
||||||
uintptr_t *names = cx->tempLifoAlloc().newArray<uintptr_t>(bindings.length());
|
// Store the LifoAlloc::Mark right before the allocation.
|
||||||
if (!names) {
|
LifoAlloc::Mark mark = lifo.mark();
|
||||||
|
void *mem = lifo.alloc(sizeof(LifoAlloc::Mark) + bindings.length() * sizeof(uintptr_t));
|
||||||
|
if (!mem) {
|
||||||
js_ReportOutOfMemory(cx);
|
js_ReportOutOfMemory(cx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*memp = mem;
|
||||||
|
*reinterpret_cast<LifoAlloc::Mark*>(mem) = mark;
|
||||||
|
|
||||||
|
// Munge data into the API this method implements. Avert your eyes!
|
||||||
|
uintptr_t *names = reinterpret_cast<uintptr_t*>((char*)mem + sizeof(LifoAlloc::Mark));
|
||||||
for (size_t i = 0; i < bindings.length(); i++)
|
for (size_t i = 0; i < bindings.length(); i++)
|
||||||
names[i] = reinterpret_cast<uintptr_t>(bindings[i].name());
|
names[i] = reinterpret_cast<uintptr_t>(bindings[i].name());
|
||||||
|
|
||||||
@ -510,9 +515,9 @@ JS_AtomKey(JSAtom *atom)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
|
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mem)
|
||||||
{
|
{
|
||||||
cx->tempLifoAlloc().release(mark);
|
cx->tempLifoAlloc().release(*reinterpret_cast<LifoAlloc::Mark*>(mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSScript *)
|
JS_PUBLIC_API(JSScript *)
|
||||||
|
@ -98,20 +98,14 @@ class MatchPairs
|
|||||||
/* MatchPairs allocated into temporary storage, removed when out of scope. */
|
/* MatchPairs allocated into temporary storage, removed when out of scope. */
|
||||||
class ScopedMatchPairs : public MatchPairs
|
class ScopedMatchPairs : public MatchPairs
|
||||||
{
|
{
|
||||||
LifoAlloc *lifoAlloc_;
|
LifoAllocScope lifoScope_;
|
||||||
void *mark_; /* Saved original position in bump allocator. */
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Constructs an implicit LifoAllocScope. */
|
/* Constructs an implicit LifoAllocScope. */
|
||||||
ScopedMatchPairs(LifoAlloc *lifoAlloc)
|
ScopedMatchPairs(LifoAlloc *lifoAlloc)
|
||||||
: lifoAlloc_(lifoAlloc),
|
: lifoScope_(lifoAlloc)
|
||||||
mark_(lifoAlloc->mark())
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~ScopedMatchPairs() {
|
|
||||||
lifoAlloc_->release(mark_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const MatchPair &operator[](size_t i) const { return pair(i); }
|
const MatchPair &operator[](size_t i) const { return pair(i); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -169,7 +169,7 @@ ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(!pairs_);
|
JS_ASSERT(!pairs_);
|
||||||
pairs_ = (MatchPair *)lifoAlloc_->alloc(sizeof(MatchPair) * pairCount);
|
pairs_ = (MatchPair *)lifoScope_.alloc().alloc(sizeof(MatchPair) * pairCount);
|
||||||
if (!pairs_)
|
if (!pairs_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user