mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 831581 - Don't poison pointers embedded in the inline asm buffer; r=bhackett
--HG-- rename : docshell/test/browser/browser_bug234628-8.js => docshell/test/browser/browser_bug134911.js extra : rebase_source : 7a73219b7e2e02869b521da853a764bb34a3cef6
This commit is contained in:
parent
7cc374989b
commit
5012959b6b
@ -40,8 +40,10 @@
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsopcode.h"
|
||||
|
||||
#include "gc/Root.h"
|
||||
#include "methodjit/Logging.h"
|
||||
#include "ion/IonSpewer.h"
|
||||
|
||||
@ -63,6 +65,9 @@ namespace JSC {
|
||||
, m_capacity(inlineCapacity)
|
||||
, m_size(0)
|
||||
, m_oom(false)
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
, m_skipInline(js::TlsPerThreadData.get(), &m_inlineBuffer)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -246,6 +251,17 @@ namespace JSC {
|
||||
int m_capacity;
|
||||
int m_size;
|
||||
bool m_oom;
|
||||
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
/*
|
||||
* GC Pointers baked into the code can get stored on the stack here
|
||||
* through the inline assembler buffer. We need to protect these from
|
||||
* being poisoned by the rooting analysis, however, they do not need to
|
||||
* actually be traced: the compiler is only allowed to bake in
|
||||
* non-nursery-allocated pointers, such as Shapes.
|
||||
*/
|
||||
js::SkipRoot m_skipInline;
|
||||
#endif
|
||||
};
|
||||
|
||||
class GenericAssembler
|
||||
|
@ -609,40 +609,7 @@ class Rooted : public RootedBase<T>
|
||||
#endif
|
||||
}
|
||||
|
||||
void init(JSRuntime *rtArg) {
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::getMainThread(rtArg);
|
||||
commonInit(pt->thingGCRooters);
|
||||
#endif
|
||||
}
|
||||
|
||||
void init(js::PerThreadData *ptArg) {
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::get(ptArg);
|
||||
commonInit(pt->thingGCRooters);
|
||||
#endif
|
||||
#if defined(JSGC_ROOT_ANALYSIS)
|
||||
scanned = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
Rooted(JSRuntime *rt
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(RootMethods<T>::initial())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(rt);
|
||||
}
|
||||
|
||||
Rooted(JSRuntime *rt, T initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(initial)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(rt);
|
||||
}
|
||||
|
||||
Rooted(JSContext *cx
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(RootMethods<T>::initial())
|
||||
@ -659,22 +626,6 @@ class Rooted : public RootedBase<T>
|
||||
init(cx);
|
||||
}
|
||||
|
||||
Rooted(js::PerThreadData *pt
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(RootMethods<T>::initial())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(pt);
|
||||
}
|
||||
|
||||
Rooted(js::PerThreadData *pt, T initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(initial)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(pt);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
Rooted(JSContext *cx, const Unrooted<S> &initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
@ -787,8 +738,8 @@ class SkipRoot
|
||||
const uint8_t *end;
|
||||
|
||||
template <typename T>
|
||||
void init(ContextFriendFields *cx, const T *ptr, size_t count) {
|
||||
this->stack = &cx->skipGCRooters;
|
||||
void init(SkipRoot **head, const T *ptr, size_t count) {
|
||||
this->stack = head;
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
this->start = (const uint8_t *) ptr;
|
||||
@ -800,7 +751,16 @@ class SkipRoot
|
||||
SkipRoot(JSContext *cx, const T *ptr, size_t count = 1
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
init(ContextFriendFields::get(cx), ptr, count);
|
||||
init(&ContextFriendFields::get(cx)->skipGCRooters, ptr, count);
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SkipRoot(js::PerThreadData *ptd, const T *ptr, size_t count = 1
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
PerThreadDataFriendFields *ptff = PerThreadDataFriendFields::get(ptd);
|
||||
init(&ptff->skipGCRooters, ptr, count);
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
@ -825,6 +785,13 @@ class SkipRoot
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SkipRoot(PerThreadData *ptd, const T *ptr, size_t count = 1
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
|
||||
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
@ -43,7 +43,7 @@ typedef RootedValueMap::Enum RootEnum;
|
||||
|
||||
#ifdef JSGC_USE_EXACT_ROOTING
|
||||
static inline void
|
||||
MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
|
||||
MarkExactStackRoot(JSTracer *trc, Rooted<void*> *rooter, ThingRootKind kind)
|
||||
{
|
||||
void **addr = (void **)rooter->address();
|
||||
if (!*addr)
|
||||
@ -51,7 +51,7 @@ MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
|
||||
|
||||
switch (kind) {
|
||||
case THING_ROOT_OBJECT: MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break;
|
||||
case THING_ROOT_STRING: MarkStringRoot(trc, (JSSTring **)addr, "exact-string"); break;
|
||||
case THING_ROOT_STRING: MarkStringRoot(trc, (JSString **)addr, "exact-string"); break;
|
||||
case THING_ROOT_SCRIPT: MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break;
|
||||
case THING_ROOT_SHAPE: MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break;
|
||||
case THING_ROOT_BASE_SHAPE: MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break;
|
||||
@ -66,11 +66,10 @@ MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
|
||||
}
|
||||
|
||||
static inline void
|
||||
MarkExactStackRooters(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
|
||||
MarkExactStackRootList(JSTracer *trc, Rooted<void*> *rooter, ThingRootKind kind)
|
||||
{
|
||||
Rooted<void*> *rooter = cx->thingGCRooters[i];
|
||||
while (rooter) {
|
||||
MarkExactStackRoot(trc, rooter, ThingRootKind(i));
|
||||
MarkExactStackRoot(trc, rooter, kind);
|
||||
rooter = rooter->previous();
|
||||
}
|
||||
}
|
||||
@ -79,10 +78,8 @@ static void
|
||||
MarkExactStackRoots(JSTracer *trc)
|
||||
{
|
||||
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
|
||||
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
|
||||
MarkExactStackRooters(trc, cx->thingGCRooters[i], ThingRootKind(i));
|
||||
}
|
||||
MarkExactStackRooters(trc, rt->mainThread.thingGCRooters[i], ThingRootKind(i));
|
||||
for (ContextIter cx(trc->runtime); !cx.done(); cx.next())
|
||||
MarkExactStackRootList(trc, cx->thingGCRooters[i], ThingRootKind(i));
|
||||
}
|
||||
}
|
||||
#endif /* JSGC_USE_EXACT_ROOTING */
|
||||
|
@ -70,8 +70,14 @@ CheckStackRoot(JSRuntime *rt, uintptr_t *w, Rooter *begin, Rooter *end)
|
||||
return;
|
||||
}
|
||||
|
||||
SkipRoot *skip = TlsPerThreadData.get()->skipGCRooters;
|
||||
while (skip) {
|
||||
if (skip->contains(reinterpret_cast<uint8_t*>(w), sizeof(w)))
|
||||
return;
|
||||
skip = skip->previous();
|
||||
}
|
||||
for (ContextIter cx(rt); !cx.done(); cx.next()) {
|
||||
SkipRoot *skip = cx->skipGCRooters;
|
||||
skip = cx->skipGCRooters;
|
||||
while (skip) {
|
||||
if (skip->contains(reinterpret_cast<uint8_t*>(w), sizeof(w)))
|
||||
return;
|
||||
@ -239,14 +245,8 @@ JS::CheckStackRoots(JSContext *cx)
|
||||
// Gather up all of the rooters
|
||||
Vector< Rooter, 0, SystemAllocPolicy> rooters;
|
||||
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
|
||||
Rooted<void*> *rooter = rt->mainThread.thingGCRooters[i];
|
||||
while (rooter) {
|
||||
Rooter r = { rooter, ThingRootKind(i) };
|
||||
JS_ALWAYS_TRUE(rooters.append(r));
|
||||
rooter = rooter->previous();
|
||||
}
|
||||
for (ContextIter cx(rt); !cx.done(); cx.next()) {
|
||||
rooter = cx->thingGCRooters[i];
|
||||
Rooted<void*> *rooter = cx->thingGCRooters[i];
|
||||
while (rooter) {
|
||||
Rooter r = { rooter, ThingRootKind(i) };
|
||||
JS_ALWAYS_TRUE(rooters.append(r));
|
||||
|
@ -100,13 +100,17 @@ struct ImmGCPtr
|
||||
uintptr_t value;
|
||||
|
||||
explicit ImmGCPtr(const gc::Cell *ptr) : value(reinterpret_cast<uintptr_t>(ptr))
|
||||
{ }
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedPtr(ptr));
|
||||
}
|
||||
|
||||
// ImmGCPtr is rooted so we can convert safely directly from Unrooted<T>.
|
||||
template <typename T>
|
||||
explicit ImmGCPtr(Unrooted<T> ptr)
|
||||
: value(reinterpret_cast<uintptr_t>(static_cast<T>(ptr)))
|
||||
{ }
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedPtr(static_cast<T>(ptr)));
|
||||
}
|
||||
};
|
||||
|
||||
// Specifies a hardcoded, absolute address.
|
||||
|
@ -27,8 +27,8 @@ JS_STATIC_ASSERT(offsetof(JSRuntime, mainThread) == sizeof(RuntimeFriendFields))
|
||||
|
||||
PerThreadDataFriendFields::PerThreadDataFriendFields()
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PodArrayZero(thingGCRooters);
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
skipGCRooters = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -319,12 +319,16 @@ struct PerThreadDataFriendFields
|
||||
{
|
||||
PerThreadDataFriendFields();
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
/*
|
||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||
* overwritten if moved during a GC.
|
||||
* Stack allocated list of stack locations which hold non-relocatable
|
||||
* GC heap pointers (where the target is rooted somewhere else) or integer
|
||||
* values which may be confused for GC heap pointers. These are used to
|
||||
* suppress false positives which occur when a rooting analysis treats the
|
||||
* location as holding a relocatable pointer, but have no other effect on
|
||||
* GC behavior.
|
||||
*/
|
||||
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||
SkipRoot *skipGCRooters;
|
||||
#endif
|
||||
|
||||
static PerThreadDataFriendFields *get(js::PerThreadData *pt) {
|
||||
|
Loading…
Reference in New Issue
Block a user