зеркало из https://github.com/mozilla/gecko-dev.git
Bug 850080 - Make root analysis check Rooted<Value> as a non-pointer type; r=sfink
In 32bit builds, Value does not have the same size as void*; thus, we cannot do a simple address comparison in this case. --HG-- extra : rebase_source : 1dfb86965c1aa873c26660b67d9add0d5d0a91d7
This commit is contained in:
Родитель
e988bc20b0
Коммит
c2d90b6f23
|
@ -28,24 +28,30 @@ using namespace js::gc;
|
|||
using namespace mozilla;
|
||||
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
# if JS_STACK_GROWTH_DIRECTION > 0
|
||||
# error "Root analysis is only supported on a descending stack."
|
||||
# endif
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
CheckNonAddressThing(uintptr_t *w, T *t)
|
||||
CheckNonAddressThing(uintptr_t *w, Rooted<T> *rootp)
|
||||
{
|
||||
return w >= (uintptr_t*)t && w < (uintptr_t*)(t + 1);
|
||||
return w >= (uintptr_t*)rootp->address() && w < (uintptr_t*)(rootp->address() + 1);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
CheckStackRootThing(uintptr_t *w, void *address, ThingRootKind kind)
|
||||
CheckStackRootThing(uintptr_t *w, Rooted<void *> *rootp, ThingRootKind kind)
|
||||
{
|
||||
if (kind == THING_ROOT_BINDINGS)
|
||||
return CheckNonAddressThing(w, static_cast<Bindings*>(address));
|
||||
return CheckNonAddressThing(w, reinterpret_cast<Rooted<Bindings> *>(rootp));
|
||||
|
||||
if (kind == THING_ROOT_PROPERTY_DESCRIPTOR)
|
||||
return CheckNonAddressThing(w, static_cast<PropertyDescriptor*>(address));
|
||||
return CheckNonAddressThing(w, reinterpret_cast<Rooted<PropertyDescriptor> *>(rootp));
|
||||
|
||||
return address == static_cast<void*>(w);
|
||||
if (kind == THING_ROOT_VALUE)
|
||||
return CheckNonAddressThing(w, reinterpret_cast<Rooted<Value> *>(rootp));
|
||||
|
||||
return rootp->address() == static_cast<void*>(w);
|
||||
}
|
||||
|
||||
struct Rooter {
|
||||
|
@ -76,7 +82,7 @@ CheckStackRoot(JSRuntime *rt, uintptr_t *w, Rooter *begin, Rooter *end)
|
|||
*/
|
||||
|
||||
for (Rooter *p = begin; p != end; p++) {
|
||||
if (CheckStackRootThing(w, p->rooter->address(), p->kind))
|
||||
if (CheckStackRootThing(w, p->rooter, p->kind))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -122,7 +128,7 @@ CheckStackRootsRangeAndSkipIon(JSRuntime *rt, uintptr_t *begin, uintptr_t *end,
|
|||
*/
|
||||
uintptr_t *i = begin;
|
||||
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
|
||||
#if defined(JS_ION)
|
||||
for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
|
||||
uintptr_t *ionMin, *ionEnd;
|
||||
ion.ionStackRange(ionMin, ionEnd);
|
||||
|
@ -177,15 +183,15 @@ SuppressCheckRoots(Vector<Rooter, 0, SystemAllocPolicy> &rooters)
|
|||
qsort(rooters.begin(), rooters.length(), sizeof(Rooter), CompareRooters);
|
||||
|
||||
// Forward-declare a variable so its address can be used to mark the
|
||||
// current top of the stack
|
||||
// current top of the stack.
|
||||
unsigned int pos;
|
||||
|
||||
// Compute the hash of the current stack
|
||||
// Compute the hash of the current stack.
|
||||
uint32_t hash = HashGeneric(&pos);
|
||||
for (unsigned int i = 0; i < Min(StackCheckDepth, rooters.length()); i++)
|
||||
hash = AddToHash(hash, rooters[rooters.length() - i - 1].rooter);
|
||||
|
||||
// Scan through the remembered stacks to find the current stack
|
||||
// Scan through the remembered stacks to find the current stack.
|
||||
for (pos = 0; pos < numMemories; pos++) {
|
||||
if (stacks[pos] == hash) {
|
||||
// Skip this check. Technically, it is incorrect to not update the
|
||||
|
@ -195,7 +201,7 @@ SuppressCheckRoots(Vector<Rooter, 0, SystemAllocPolicy> &rooters)
|
|||
}
|
||||
}
|
||||
|
||||
// Replace the oldest remembered stack with our current stack
|
||||
// Replace the oldest remembered stack with our current stack.
|
||||
stacks[oldestMemory] = hash;
|
||||
oldestMemory = (oldestMemory + 1) % NumStackMemories;
|
||||
if (numMemories < NumStackMemories)
|
||||
|
@ -247,13 +253,9 @@ JS::CheckStackRoots(JSContext *cx)
|
|||
|
||||
JS_ASSERT(cgcd->hasStackToScan());
|
||||
uintptr_t *stackMin, *stackEnd;
|
||||
#if JS_STACK_GROWTH_DIRECTION > 0
|
||||
stackMin = rt->nativeStackBase;
|
||||
stackEnd = cgcd->nativeStackTop;
|
||||
#else
|
||||
stackMin = cgcd->nativeStackTop + 1;
|
||||
stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
|
||||
#endif
|
||||
JS_ASSERT(stackMin <= stackEnd);
|
||||
|
||||
// Gather up all of the rooters
|
||||
Vector<Rooter, 0, SystemAllocPolicy> rooters;
|
||||
|
@ -275,12 +277,7 @@ JS::CheckStackRoots(JSContext *cx)
|
|||
for (Rooter *p = rooters.begin(); p != rooters.end(); p++) {
|
||||
if (p->rooter->scanned) {
|
||||
uintptr_t *addr = reinterpret_cast<uintptr_t*>(p->rooter);
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0
|
||||
if (stackEnd > addr)
|
||||
#else
|
||||
if (stackEnd < addr)
|
||||
#endif
|
||||
{
|
||||
if (stackEnd > addr) {
|
||||
stackEnd = addr;
|
||||
firstScanned = p->rooter;
|
||||
}
|
||||
|
@ -292,25 +289,19 @@ JS::CheckStackRoots(JSContext *cx)
|
|||
Rooter *firstToScan = rooters.begin();
|
||||
if (firstScanned) {
|
||||
for (Rooter *p = rooters.begin(); p != rooters.end(); p++) {
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0
|
||||
if (p->rooter >= firstScanned)
|
||||
#else
|
||||
if (p->rooter <= firstScanned)
|
||||
#endif
|
||||
{
|
||||
if (p->rooter >= firstScanned) {
|
||||
Swap(*firstToScan, *p);
|
||||
++firstToScan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(stackMin <= stackEnd);
|
||||
CheckStackRootsRangeAndSkipIon(rt, stackMin, stackEnd, firstToScan, rooters.end());
|
||||
CheckStackRootsRange(rt, cgcd->registerSnapshot.words,
|
||||
ArrayEnd(cgcd->registerSnapshot.words),
|
||||
firstToScan, rooters.end());
|
||||
|
||||
// Mark all rooters as scanned
|
||||
// Mark all rooters as scanned.
|
||||
for (Rooter *p = rooters.begin(); p != rooters.end(); p++)
|
||||
p->rooter->scanned = true;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче