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));
|
||||
}
|
||||
|
||||
void *mark() {
|
||||
markCount++;
|
||||
class Mark {
|
||||
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--;
|
||||
|
||||
if (!mark) {
|
||||
if (!mark.chunk) {
|
||||
latest = first;
|
||||
if (latest)
|
||||
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() {
|
||||
@ -381,18 +380,19 @@ class LifoAlloc
|
||||
|
||||
class LifoAllocScope
|
||||
{
|
||||
LifoAlloc *lifoAlloc;
|
||||
void *mark;
|
||||
bool shouldRelease;
|
||||
LifoAlloc *lifoAlloc;
|
||||
LifoAlloc::Mark mark;
|
||||
bool shouldRelease;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit LifoAllocScope(LifoAlloc *lifoAlloc
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: lifoAlloc(lifoAlloc), shouldRelease(true)
|
||||
: lifoAlloc(lifoAlloc),
|
||||
mark(lifoAlloc->mark()),
|
||||
shouldRelease(true)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
mark = lifoAlloc->mark();
|
||||
}
|
||||
|
||||
~LifoAllocScope() {
|
||||
|
@ -384,7 +384,6 @@ Parser<ParseHandler>::Parser(JSContext *cx, const CompileOptions &options,
|
||||
: AutoGCRooter(cx, PARSER),
|
||||
context(cx),
|
||||
tokenStream(cx, options, chars, length, thisForCtor()),
|
||||
tempPoolMark(NULL),
|
||||
traceListHead(NULL),
|
||||
pc(NULL),
|
||||
sct(NULL),
|
||||
|
@ -263,7 +263,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
|
||||
{
|
||||
JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
|
||||
TokenStream tokenStream;
|
||||
void *tempPoolMark; /* initial JSContext.tempLifoAlloc mark */
|
||||
LifoAlloc::Mark tempPoolMark;
|
||||
|
||||
/* list of parsed objects for GC tracing */
|
||||
ObjectBox *traceListHead;
|
||||
|
@ -20,34 +20,27 @@ namespace ion {
|
||||
|
||||
class TempAllocator
|
||||
{
|
||||
LifoAlloc *lifoAlloc_;
|
||||
void *mark_;
|
||||
LifoAllocScope lifoScope_;
|
||||
|
||||
// Linked list of GCThings rooted by this allocator.
|
||||
CompilerRootNode *rootList_;
|
||||
|
||||
public:
|
||||
TempAllocator(LifoAlloc *lifoAlloc)
|
||||
: lifoAlloc_(lifoAlloc),
|
||||
mark_(lifoAlloc->mark()),
|
||||
: lifoScope_(lifoAlloc),
|
||||
rootList_(NULL)
|
||||
{ }
|
||||
|
||||
~TempAllocator()
|
||||
{
|
||||
lifoAlloc_->release(mark_);
|
||||
}
|
||||
|
||||
void *allocateInfallible(size_t bytes)
|
||||
{
|
||||
void *p = lifoAlloc_->allocInfallible(bytes);
|
||||
void *p = lifoScope_.alloc().allocInfallible(bytes);
|
||||
JS_ASSERT(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *allocate(size_t bytes)
|
||||
{
|
||||
void *p = lifoAlloc_->alloc(bytes);
|
||||
void *p = lifoScope_.alloc().alloc(bytes);
|
||||
if (!ensureBallast())
|
||||
return NULL;
|
||||
return p;
|
||||
@ -55,7 +48,7 @@ class TempAllocator
|
||||
|
||||
LifoAlloc *lifoAlloc()
|
||||
{
|
||||
return lifoAlloc_;
|
||||
return &lifoScope_.alloc();
|
||||
}
|
||||
|
||||
CompilerRootNode *&rootList()
|
||||
@ -66,7 +59,7 @@ class TempAllocator
|
||||
bool ensureBallast() {
|
||||
// Most infallible Ion allocations are small, so we use a ballast of
|
||||
// ~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 *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **memp)
|
||||
{
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
BindingVector bindings(cx);
|
||||
if (!FillBindingVector(script, &bindings))
|
||||
return NULL;
|
||||
|
||||
/* Munge data into the API this method implements. Avert your eyes! */
|
||||
*markp = cx->tempLifoAlloc().mark();
|
||||
LifoAlloc &lifo = cx->tempLifoAlloc();
|
||||
|
||||
uintptr_t *names = cx->tempLifoAlloc().newArray<uintptr_t>(bindings.length());
|
||||
if (!names) {
|
||||
// Store the LifoAlloc::Mark right before the allocation.
|
||||
LifoAlloc::Mark mark = lifo.mark();
|
||||
void *mem = lifo.alloc(sizeof(LifoAlloc::Mark) + bindings.length() * sizeof(uintptr_t));
|
||||
if (!mem) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
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++)
|
||||
names[i] = reinterpret_cast<uintptr_t>(bindings[i].name());
|
||||
|
||||
@ -510,9 +515,9 @@ JS_AtomKey(JSAtom *atom)
|
||||
}
|
||||
|
||||
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 *)
|
||||
|
@ -98,20 +98,14 @@ class MatchPairs
|
||||
/* MatchPairs allocated into temporary storage, removed when out of scope. */
|
||||
class ScopedMatchPairs : public MatchPairs
|
||||
{
|
||||
LifoAlloc *lifoAlloc_;
|
||||
void *mark_; /* Saved original position in bump allocator. */
|
||||
LifoAllocScope lifoScope_;
|
||||
|
||||
public:
|
||||
/* Constructs an implicit LifoAllocScope. */
|
||||
ScopedMatchPairs(LifoAlloc *lifoAlloc)
|
||||
: lifoAlloc_(lifoAlloc),
|
||||
mark_(lifoAlloc->mark())
|
||||
: lifoScope_(lifoAlloc)
|
||||
{ }
|
||||
|
||||
~ScopedMatchPairs() {
|
||||
lifoAlloc_->release(mark_);
|
||||
}
|
||||
|
||||
const MatchPair &operator[](size_t i) const { return pair(i); }
|
||||
|
||||
protected:
|
||||
|
@ -169,7 +169,7 @@ ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
|
||||
}
|
||||
|
||||
JS_ASSERT(!pairs_);
|
||||
pairs_ = (MatchPair *)lifoAlloc_->alloc(sizeof(MatchPair) * pairCount);
|
||||
pairs_ = (MatchPair *)lifoScope_.alloc().alloc(sizeof(MatchPair) * pairCount);
|
||||
if (!pairs_)
|
||||
return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user