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:
Terrence Cole 2013-05-29 15:46:08 -07:00
Родитель e988bc20b0
Коммит c2d90b6f23
1 изменённых файлов: 22 добавлений и 31 удалений

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

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