mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 807480 - Add Rooted<T> roots to PerThread state. r=luke
Currently there are a number of global fields in JSRuntime* which are basically tracking per-thread state. This makes sense on the current trunk since there is only ever a single thread associated with a runtime, but as Parallel JS (nee Rivertrail) starts to land this assumption no longer holds. This patch makes a struct, currently called |JS::PerThreadData|, that stores per-thread data from the runtime. There is one instance of this struct embedded in "Runtime" itself (the field |mainThread|). For now I have only migrated the debug GC fields into |PerThread|, those are the ones causing me immediate pain. Eventually more fields will want to move into there. The eventual goal is to distinguish thread-safe code, which will take as argument a |JS::PerThread*|, from non-thread-safe code, which will take a |JSRuntime*| or |JSContext*|.
This commit is contained in:
parent
6240239870
commit
0f88896f1a
@ -519,27 +519,23 @@ class Rooted : public RootedBase<T>
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cxArg);
|
||||
|
||||
ThingRootKind kind = RootMethods<T>::kind();
|
||||
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
|
||||
commonInit(cx->thingGCRooters);
|
||||
#endif
|
||||
}
|
||||
|
||||
void init(JSRuntime *rtArg)
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
RuntimeFriendFields *rt = const_cast<RuntimeFriendFields *>(RuntimeFriendFields::get(rtArg));
|
||||
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::getMainThread(rtArg);
|
||||
commonInit(pt->thingGCRooters);
|
||||
#endif
|
||||
}
|
||||
|
||||
ThingRootKind kind = RootMethods<T>::kind();
|
||||
this->stack = reinterpret_cast<Rooted<T>**>(&rt->thingGCRooters[kind]);
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
|
||||
void init(js::PerThreadData *ptArg)
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::get(ptArg);
|
||||
commonInit(pt->thingGCRooters);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -576,6 +572,22 @@ 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 Return<S> &initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
@ -585,6 +597,15 @@ class Rooted : public RootedBase<T>
|
||||
init(cx);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
Rooted(js::PerThreadData *pt, const Return<S> &initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(initial.ptr_)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
init(pt);
|
||||
}
|
||||
|
||||
~Rooted()
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
@ -625,6 +646,17 @@ class Rooted : public RootedBase<T>
|
||||
}
|
||||
|
||||
private:
|
||||
void commonInit(Rooted<void*> **thingGCRooters) {
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
ThingRootKind kind = RootMethods<T>::kind();
|
||||
this->stack = reinterpret_cast<Rooted<T>**>(&thingGCRooters[kind]);
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
Rooted<T> **stack, *prev;
|
||||
#endif
|
||||
|
@ -676,33 +676,36 @@ static JSBool js_NewRuntimeWasCalled = JS_FALSE;
|
||||
/*
|
||||
* Thread Local Storage slot for storing the runtime for a thread.
|
||||
*/
|
||||
namespace js {
|
||||
mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(void)
|
||||
EnterAssertNoGCScope()
|
||||
{
|
||||
++TlsRuntime.get()->gcAssertNoGCDepth;
|
||||
++TlsPerThreadData.get()->gcAssertNoGCDepth;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
LeaveAssertNoGCScope()
|
||||
{
|
||||
--TlsRuntime.get()->gcAssertNoGCDepth;
|
||||
JS_ASSERT(TlsRuntime.get()->gcAssertNoGCDepth >= 0);
|
||||
--TlsPerThreadData.get()->gcAssertNoGCDepth;
|
||||
JS_ASSERT(TlsPerThreadData.get()->gcAssertNoGCDepth >= 0);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
InNoGCScope()
|
||||
{
|
||||
return TlsRuntime.get()->gcAssertNoGCDepth > 0;
|
||||
return TlsPerThreadData.get()->gcAssertNoGCDepth > 0;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
NeedRelaxedRootChecks()
|
||||
{
|
||||
return TlsRuntime.get()->gcRelaxRootChecks;
|
||||
return TlsPerThreadData.get()->gcRelaxRootChecks;
|
||||
}
|
||||
#else
|
||||
JS_FRIEND_API(void) EnterAssertNoGCScope() {}
|
||||
@ -715,8 +718,17 @@ JS_FRIEND_API(bool) NeedRelaxedRootChecks() { return false; }
|
||||
|
||||
static const JSSecurityCallbacks NullSecurityCallbacks = { };
|
||||
|
||||
js::PerThreadData::PerThreadData(JSRuntime *runtime)
|
||||
: runtime_(runtime)
|
||||
#ifdef DEBUG
|
||||
, gcRelaxRootChecks(false)
|
||||
, gcAssertNoGCDepth(0)
|
||||
#endif
|
||||
{}
|
||||
|
||||
JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
: atomsCompartment(NULL),
|
||||
: mainThread(this),
|
||||
atomsCompartment(NULL),
|
||||
#ifdef JS_THREADSAFE
|
||||
ownerThread_(NULL),
|
||||
#endif
|
||||
@ -788,10 +800,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
gcSliceBudget(SliceBudget::Unlimited),
|
||||
gcIncrementalEnabled(true),
|
||||
gcExactScanningEnabled(true),
|
||||
#ifdef DEBUG
|
||||
gcRelaxRootChecks(false),
|
||||
gcAssertNoGCDepth(0),
|
||||
#endif
|
||||
gcPoke(false),
|
||||
heapState(Idle),
|
||||
#ifdef JS_GC_ZEAL
|
||||
@ -885,16 +893,12 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
ownerThread_ = PR_GetCurrentThread();
|
||||
#endif
|
||||
|
||||
JS::TlsRuntime.set(this);
|
||||
js::TlsPerThreadData.set(&mainThread);
|
||||
|
||||
#ifdef JS_METHODJIT_SPEW
|
||||
JMCheckLogging();
|
||||
#endif
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PodArrayZero(thingGCRooters);
|
||||
#endif
|
||||
|
||||
if (!js_InitGC(this, maxbytes))
|
||||
return false;
|
||||
|
||||
@ -1018,9 +1022,9 @@ JSRuntime::setOwnerThread()
|
||||
JS_ASSERT(ownerThread_ == (void *)0xc1ea12); /* "clear" */
|
||||
JS_ASSERT(requestDepth == 0);
|
||||
JS_ASSERT(js_NewRuntimeWasCalled);
|
||||
JS_ASSERT(JS::TlsRuntime.get() == NULL);
|
||||
JS_ASSERT(js::TlsPerThreadData.get() == NULL);
|
||||
ownerThread_ = PR_GetCurrentThread();
|
||||
JS::TlsRuntime.set(this);
|
||||
js::TlsPerThreadData.set(&mainThread);
|
||||
nativeStackBase = GetNativeStackBase();
|
||||
if (nativeStackQuota)
|
||||
JS_SetNativeStackQuota(this, nativeStackQuota);
|
||||
@ -1033,7 +1037,7 @@ JSRuntime::clearOwnerThread()
|
||||
JS_ASSERT(requestDepth == 0);
|
||||
JS_ASSERT(js_NewRuntimeWasCalled);
|
||||
ownerThread_ = (void *)0xc1ea12; /* "clear" */
|
||||
JS::TlsRuntime.set(NULL);
|
||||
js::TlsPerThreadData.set(NULL);
|
||||
nativeStackBase = 0;
|
||||
#if JS_STACK_GROWTH_DIRECTION > 0
|
||||
nativeStackLimit = UINTPTR_MAX;
|
||||
@ -1047,7 +1051,7 @@ JSRuntime::abortIfWrongThread() const
|
||||
{
|
||||
if (ownerThread_ != PR_GetCurrentThread())
|
||||
MOZ_CRASH();
|
||||
if (this != JS::TlsRuntime.get())
|
||||
if (!js::TlsPerThreadData.get()->associatedWith(this))
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
@ -1055,7 +1059,7 @@ JS_FRIEND_API(void)
|
||||
JSRuntime::assertValidThread() const
|
||||
{
|
||||
JS_ASSERT(ownerThread_ == PR_GetCurrentThread());
|
||||
JS_ASSERT(this == JS::TlsRuntime.get());
|
||||
JS_ASSERT(js::TlsPerThreadData.get()->associatedWith(this));
|
||||
}
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
@ -1092,7 +1096,7 @@ JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads)
|
||||
|
||||
InitMemorySubsystem();
|
||||
|
||||
if (!JS::TlsRuntime.init())
|
||||
if (!js::TlsPerThreadData.init())
|
||||
return NULL;
|
||||
|
||||
js_NewRuntimeWasCalled = JS_TRUE;
|
||||
|
@ -2889,8 +2889,6 @@ JS_IsInRequest(JSRuntime *rt);
|
||||
|
||||
namespace JS {
|
||||
|
||||
extern mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
|
||||
|
||||
inline bool
|
||||
IsPoisonedId(jsid iden)
|
||||
{
|
||||
|
@ -389,8 +389,70 @@ struct JSAtomState
|
||||
#define NAME_OFFSET(name) offsetof(JSAtomState, name)
|
||||
#define OFFSET_TO_NAME(rt,off) (*(js::FixedHeapPtr<js::PropertyName>*)((char*)&(rt)->atomState + (off)))
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Encapsulates portions of the runtime/context that are tied to a
|
||||
* single active thread. Normally, as most JS is single-threaded,
|
||||
* there is only one instance of this struct, embedded in the
|
||||
* JSRuntime as the field |mainThread|. During Parallel JS sections,
|
||||
* however, there will be one instance per worker thread.
|
||||
*
|
||||
* The eventual plan is to designate thread-safe portions of the
|
||||
* interpreter and runtime by having them take |PerThreadData*|
|
||||
* arguments instead of |JSContext*| or |JSRuntime*|.
|
||||
*/
|
||||
class PerThreadData : public js::PerThreadDataFriendFields
|
||||
{
|
||||
/*
|
||||
* Backpointer to the full shared JSRuntime* with which this
|
||||
* thread is associaed. This is private because accessing the
|
||||
* fields of this runtime can provoke race conditions, so the
|
||||
* intention is that access will be mediated through safe
|
||||
* functions like |associatedWith()| below.
|
||||
*/
|
||||
JSRuntime *runtime_;
|
||||
|
||||
public:
|
||||
/*
|
||||
* We save all conservative scanned roots in this vector so that
|
||||
* conservative scanning can be "replayed" deterministically. In DEBUG mode,
|
||||
* this allows us to run a non-incremental GC after every incremental GC to
|
||||
* ensure that no objects were missed.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
struct SavedGCRoot {
|
||||
void *thing;
|
||||
JSGCTraceKind kind;
|
||||
|
||||
SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
|
||||
};
|
||||
js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
|
||||
|
||||
bool gcRelaxRootChecks;
|
||||
int gcAssertNoGCDepth;
|
||||
#endif
|
||||
|
||||
PerThreadData(JSRuntime *runtime);
|
||||
|
||||
bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
struct JSRuntime : js::RuntimeFriendFields
|
||||
{
|
||||
/* Per-thread data for the main thread that is associated with
|
||||
* this JSRuntime, as opposed to any worker threads used in
|
||||
* parallel sections. See definition of |PerThreadData| struct
|
||||
* above for more details.
|
||||
*
|
||||
* NB: This field is statically asserted to be at offset
|
||||
* sizeof(RuntimeFriendFields). See
|
||||
* PerThreadDataFriendFields::getMainThread.
|
||||
*/
|
||||
js::PerThreadData mainThread;
|
||||
|
||||
/* Default compartment. */
|
||||
JSCompartment *atomsCompartment;
|
||||
|
||||
@ -654,25 +716,6 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
*/
|
||||
bool gcExactScanningEnabled;
|
||||
|
||||
/*
|
||||
* We save all conservative scanned roots in this vector so that
|
||||
* conservative scanning can be "replayed" deterministically. In DEBUG mode,
|
||||
* this allows us to run a non-incremental GC after every incremental GC to
|
||||
* ensure that no objects were missed.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
struct SavedGCRoot {
|
||||
void *thing;
|
||||
JSGCTraceKind kind;
|
||||
|
||||
SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
|
||||
};
|
||||
js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
|
||||
|
||||
bool gcRelaxRootChecks;
|
||||
int gcAssertNoGCDepth;
|
||||
#endif
|
||||
|
||||
bool gcPoke;
|
||||
|
||||
enum HeapState {
|
||||
|
@ -22,6 +22,16 @@
|
||||
using namespace js;
|
||||
using namespace JS;
|
||||
|
||||
// Required by PerThreadDataFriendFields::getMainThread()
|
||||
JS_STATIC_ASSERT(offsetof(JSRuntime, mainThread) == sizeof(RuntimeFriendFields));
|
||||
|
||||
PerThreadDataFriendFields::PerThreadDataFriendFields()
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
PodArrayZero(thingGCRooters);
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook)
|
||||
{
|
||||
|
@ -183,6 +183,8 @@ JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
|
||||
|
||||
inline JSRuntime *
|
||||
GetRuntime(const JSContext *cx)
|
||||
{
|
||||
|
@ -992,7 +992,7 @@ MarkExactStackRoots(JSTracer *trc)
|
||||
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
|
||||
MarkExactStackRooters(trc, cx->thingGCRooters[i], ThingRootKind(i));
|
||||
}
|
||||
MarkExactStackRooters(trc, rt->thingGCRooters[i], ThingRootKind(i));
|
||||
MarkExactStackRooters(trc, rt->mainThread.thingGCRooters[i], ThingRootKind(i));
|
||||
}
|
||||
}
|
||||
#endif /* JSGC_USE_EXACT_ROOTING */
|
||||
@ -1125,7 +1125,8 @@ MarkIfGCThingWord(JSTracer *trc, uintptr_t w)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (trc->runtime->gcIncrementalState == MARK_ROOTS)
|
||||
trc->runtime->gcSavedRoots.append(JSRuntime::SavedGCRoot(thing, traceKind));
|
||||
trc->runtime->mainThread.gcSavedRoots.append(
|
||||
PerThreadData::SavedGCRoot(thing, traceKind));
|
||||
#endif
|
||||
|
||||
return CGCT_VALID;
|
||||
@ -1186,8 +1187,8 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (useSavedRoots) {
|
||||
for (JSRuntime::SavedGCRoot *root = rt->gcSavedRoots.begin();
|
||||
root != rt->gcSavedRoots.end();
|
||||
for (PerThreadData::SavedGCRoot *root = rt->mainThread.gcSavedRoots.begin();
|
||||
root != rt->mainThread.gcSavedRoots.end();
|
||||
root++)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, "cstack");
|
||||
@ -1197,7 +1198,7 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
|
||||
}
|
||||
|
||||
if (rt->gcIncrementalState == MARK_ROOTS)
|
||||
rt->gcSavedRoots.clearAndFree();
|
||||
rt->mainThread.gcSavedRoots.clearAndFree();
|
||||
#endif
|
||||
|
||||
ConservativeGCData *cgcd = &rt->conservativeGC;
|
||||
@ -4912,7 +4913,8 @@ CheckStackRoot(JSTracer *trc, uintptr_t *w)
|
||||
bool matched = false;
|
||||
JSRuntime *rt = trc->runtime;
|
||||
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
|
||||
CheckStackRootThings(w, rt->thingGCRooters[i], ThingRootKind(i), &matched);
|
||||
CheckStackRootThings(w, rt->mainThread.thingGCRooters[i],
|
||||
ThingRootKind(i), &matched);
|
||||
for (ContextIter cx(rt); !cx.done(); cx.next()) {
|
||||
CheckStackRootThings(w, cx->thingGCRooters[i], ThingRootKind(i), &matched);
|
||||
SkipRoot *skip = cx->skipGCRooters;
|
||||
|
@ -307,14 +307,6 @@ struct RuntimeFriendFields {
|
||||
/* Limit pointer for checking native stack consumption. */
|
||||
uintptr_t nativeStackLimit;
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
/*
|
||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||
* overwritten if moved during a GC.
|
||||
*/
|
||||
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||
#endif
|
||||
|
||||
RuntimeFriendFields()
|
||||
: interrupt(0),
|
||||
nativeStackLimit(0) { }
|
||||
@ -324,6 +316,32 @@ struct RuntimeFriendFields {
|
||||
}
|
||||
};
|
||||
|
||||
class PerThreadData;
|
||||
|
||||
struct PerThreadDataFriendFields
|
||||
{
|
||||
PerThreadDataFriendFields();
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
/*
|
||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||
* overwritten if moved during a GC.
|
||||
*/
|
||||
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||
#endif
|
||||
|
||||
static PerThreadDataFriendFields *get(js::PerThreadData *pt) {
|
||||
return reinterpret_cast<PerThreadDataFriendFields *>(pt);
|
||||
}
|
||||
|
||||
static PerThreadDataFriendFields *getMainThread(JSRuntime *rt) {
|
||||
// mainThread must always appear directly after |RuntimeFriendFields|.
|
||||
// Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
|
||||
return reinterpret_cast<PerThreadDataFriendFields *>(
|
||||
reinterpret_cast<char*>(rt) + sizeof(RuntimeFriendFields));
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
@ -3417,7 +3417,7 @@ RelaxRootChecks(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
cx->runtime->gcRelaxRootChecks = true;
|
||||
cx->runtime->mainThread.gcRelaxRootChecks = true;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -1402,7 +1402,8 @@ StackIter::settleOnNewState()
|
||||
}
|
||||
|
||||
StackIter::StackIter(JSContext *cx, SavedOption savedOption)
|
||||
: maybecx_(cx),
|
||||
: perThread_(&cx->runtime->mainThread),
|
||||
maybecx_(cx),
|
||||
savedOption_(savedOption),
|
||||
script_(cx, NULL)
|
||||
#ifdef JS_ION
|
||||
@ -1426,7 +1427,9 @@ StackIter::StackIter(JSContext *cx, SavedOption savedOption)
|
||||
}
|
||||
|
||||
StackIter::StackIter(JSRuntime *rt, StackSegment &seg)
|
||||
: maybecx_(NULL), savedOption_(STOP_AT_SAVED),
|
||||
: perThread_(&rt->mainThread),
|
||||
maybecx_(NULL),
|
||||
savedOption_(STOP_AT_SAVED),
|
||||
script_(rt, NULL)
|
||||
#ifdef JS_ION
|
||||
, ionActivations_(rt),
|
||||
@ -1444,14 +1447,15 @@ StackIter::StackIter(JSRuntime *rt, StackSegment &seg)
|
||||
}
|
||||
|
||||
StackIter::StackIter(const StackIter &other)
|
||||
: maybecx_(other.maybecx_),
|
||||
: perThread_(other.perThread_),
|
||||
maybecx_(other.maybecx_),
|
||||
savedOption_(other.savedOption_),
|
||||
state_(other.state_),
|
||||
fp_(other.fp_),
|
||||
calls_(other.calls_),
|
||||
seg_(other.seg_),
|
||||
pc_(other.pc_),
|
||||
script_(other.maybecx_ ? other.maybecx_->runtime : TlsRuntime.get(), other.script_),
|
||||
script_(perThread_, other.script_),
|
||||
args_(other.args_)
|
||||
#ifdef JS_ION
|
||||
, ionActivations_(other.ionActivations_),
|
||||
|
@ -1712,6 +1712,7 @@ class GeneratorFrameGuard : public FrameGuard
|
||||
class StackIter
|
||||
{
|
||||
friend class ContextStack;
|
||||
PerThreadData *perThread_;
|
||||
JSContext *maybecx_;
|
||||
public:
|
||||
enum SavedOption { STOP_AT_SAVED, GO_THROUGH_SAVED };
|
||||
|
Loading…
Reference in New Issue
Block a user