mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Back out 61d58d97747a (bug 721463) on expanded suspicion of GC crashes
This commit is contained in:
parent
a8b3d39330
commit
fd7fd21135
@ -257,7 +257,7 @@ Parser::trace(JSTracer *trc)
|
||||
{
|
||||
ObjectBox *objbox = traceListHead;
|
||||
while (objbox) {
|
||||
MarkObjectRoot(trc, objbox->object, "parser.object");
|
||||
MarkRoot(trc, objbox->object, "parser.object");
|
||||
if (objbox->isFunctionBox)
|
||||
static_cast<FunctionBox *>(objbox)->bindings.trace(trc);
|
||||
objbox = objbox->traceLink;
|
||||
|
@ -4289,7 +4289,7 @@ prop_iter_trace(JSTracer *trc, JSObject *obj)
|
||||
} else {
|
||||
/* Non-native case: mark each id in the JSIdArray private. */
|
||||
JSIdArray *ida = (JSIdArray *) pdata;
|
||||
MarkIdRange(trc, ida->length, ida->vector, "prop iter");
|
||||
MarkIdRange(trc, ida->vector, ida->vector + ida->length, "prop iter");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,15 +386,16 @@ js_TraceAtomState(JSTracer *trc)
|
||||
JSAtomState *state = &rt->atomState;
|
||||
|
||||
if (rt->gcKeepAtoms) {
|
||||
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront())
|
||||
MarkStringRoot(trc, r.front().asPtr(), "locked_atom");
|
||||
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront()) {
|
||||
MarkRoot(trc, r.front().asPtr(), "locked_atom");
|
||||
}
|
||||
} else {
|
||||
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront()) {
|
||||
AtomStateEntry entry = r.front();
|
||||
if (!entry.isTagged())
|
||||
continue;
|
||||
|
||||
MarkStringRoot(trc, entry.asPtr(), "interned_atom");
|
||||
MarkRoot(trc, entry.asPtr(), "interned_atom");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
|
||||
JS_ASSERT(trc->runtime->gcCurrentCompartment);
|
||||
|
||||
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront())
|
||||
MarkValueRoot(trc, e.front().key, "cross-compartment wrapper");
|
||||
MarkRoot(trc, e.front().key, "cross-compartment wrapper");
|
||||
}
|
||||
|
||||
void
|
||||
@ -428,7 +428,7 @@ JSCompartment::markTypes(JSTracer *trc)
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
MarkScriptRoot(trc, script, "mark_types_script");
|
||||
MarkRoot(trc, script, "mark_types_script");
|
||||
}
|
||||
|
||||
for (size_t thingKind = FINALIZE_OBJECT0;
|
||||
@ -437,12 +437,12 @@ JSCompartment::markTypes(JSTracer *trc)
|
||||
for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) {
|
||||
JSObject *object = i.get<JSObject>();
|
||||
if (object->hasSingletonType())
|
||||
MarkObjectRoot(trc, object, "mark_types_singleton");
|
||||
MarkRoot(trc, object, "mark_types_singleton");
|
||||
}
|
||||
}
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next())
|
||||
MarkTypeObjectRoot(trc, i.get<types::TypeObject>(), "mark_types_scan");
|
||||
MarkRoot(trc, i.get<types::TypeObject>(), "mark_types_scan");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1879,48 +1879,50 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry)
|
||||
#endif
|
||||
const char *name = entry.value.name ? entry.value.name : "root";
|
||||
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
|
||||
MarkGCThingRoot(trc, *reinterpret_cast<void **>(entry.key), name);
|
||||
MarkRootGCThing(trc, *reinterpret_cast<void **>(entry.key), name);
|
||||
else
|
||||
MarkValueRoot(trc, *reinterpret_cast<Value *>(entry.key), name);
|
||||
MarkRoot(trc, *reinterpret_cast<Value *>(entry.key), name);
|
||||
}
|
||||
|
||||
static void
|
||||
gc_lock_traversal(const GCLocks::Entry &entry, JSTracer *trc)
|
||||
{
|
||||
JS_ASSERT(entry.value >= 1);
|
||||
MarkGCThingRoot(trc, entry.key, "locked object");
|
||||
MarkRootGCThing(trc, entry.key, "locked object");
|
||||
}
|
||||
|
||||
void
|
||||
js_TraceStackFrame(JSTracer *trc, StackFrame *fp)
|
||||
{
|
||||
MarkObjectRoot(trc, &fp->scopeChain(), "scope chain");
|
||||
MarkRoot(trc, &fp->scopeChain(), "scope chain");
|
||||
if (fp->isDummyFrame())
|
||||
return;
|
||||
if (fp->hasArgsObj())
|
||||
MarkObjectRoot(trc, &fp->argsObj(), "arguments");
|
||||
MarkRoot(trc, &fp->argsObj(), "arguments");
|
||||
if (fp->isFunctionFrame()) {
|
||||
MarkObjectRoot(trc, fp->fun(), "fun");
|
||||
if (fp->isEvalFrame())
|
||||
MarkScriptRoot(trc, fp->script(), "eval script");
|
||||
MarkRoot(trc, fp->fun(), "fun");
|
||||
if (fp->isEvalFrame()) {
|
||||
MarkRoot(trc, fp->script(), "eval script");
|
||||
}
|
||||
} else {
|
||||
MarkScriptRoot(trc, fp->script(), "script");
|
||||
MarkRoot(trc, fp->script(), "script");
|
||||
}
|
||||
fp->script()->compartment()->active = true;
|
||||
MarkValueRoot(trc, fp->returnValue(), "rval");
|
||||
MarkRoot(trc, fp->returnValue(), "rval");
|
||||
}
|
||||
|
||||
void
|
||||
AutoIdArray::trace(JSTracer *trc)
|
||||
{
|
||||
JS_ASSERT(tag == IDARRAY);
|
||||
gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
|
||||
gc::MarkIdRange(trc, idArray->vector, idArray->vector + idArray->length,
|
||||
"JSAutoIdArray.idArray");
|
||||
}
|
||||
|
||||
void
|
||||
AutoEnumStateRooter::trace(JSTracer *trc)
|
||||
{
|
||||
gc::MarkObjectRoot(trc, obj, "JS::AutoEnumStateRooter.obj");
|
||||
gc::MarkRoot(trc, obj, "JS::AutoEnumStateRooter.obj");
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -1928,7 +1930,7 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
{
|
||||
switch (tag) {
|
||||
case JSVAL:
|
||||
MarkValueRoot(trc, static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
|
||||
MarkRoot(trc, static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
|
||||
return;
|
||||
|
||||
case PARSER:
|
||||
@ -1941,7 +1943,7 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
|
||||
case IDARRAY: {
|
||||
JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
|
||||
MarkIdRange(trc, ida->length, ida->vector, "JS::AutoIdArray.idArray");
|
||||
MarkIdRange(trc, ida->vector, ida->vector + ida->length, "JS::AutoIdArray.idArray");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1950,10 +1952,10 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
static_cast<AutoPropDescArrayRooter *>(this)->descriptors;
|
||||
for (size_t i = 0, len = descriptors.length(); i < len; i++) {
|
||||
PropDesc &desc = descriptors[i];
|
||||
MarkValueRoot(trc, desc.pd, "PropDesc::pd");
|
||||
MarkValueRoot(trc, desc.value, "PropDesc::value");
|
||||
MarkValueRoot(trc, desc.get, "PropDesc::get");
|
||||
MarkValueRoot(trc, desc.set, "PropDesc::set");
|
||||
MarkRoot(trc, desc.pd, "PropDesc::pd");
|
||||
MarkRoot(trc, desc.value, "PropDesc::value");
|
||||
MarkRoot(trc, desc.get, "PropDesc::get");
|
||||
MarkRoot(trc, desc.set, "PropDesc::set");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1961,12 +1963,12 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
case DESCRIPTOR : {
|
||||
PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
|
||||
if (desc.obj)
|
||||
MarkObjectRoot(trc, desc.obj, "Descriptor::obj");
|
||||
MarkValueRoot(trc, desc.value, "Descriptor::value");
|
||||
MarkRoot(trc, desc.obj, "Descriptor::obj");
|
||||
MarkRoot(trc, desc.value, "Descriptor::value");
|
||||
if ((desc.attrs & JSPROP_GETTER) && desc.getter)
|
||||
MarkObjectRoot(trc, CastAsObject(desc.getter), "Descriptor::get");
|
||||
MarkRoot(trc, CastAsObject(desc.getter), "Descriptor::get");
|
||||
if (desc.attrs & JSPROP_SETTER && desc.setter)
|
||||
MarkObjectRoot(trc, CastAsObject(desc.setter), "Descriptor::set");
|
||||
MarkRoot(trc, CastAsObject(desc.setter), "Descriptor::set");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1983,53 +1985,52 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
|
||||
case OBJECT:
|
||||
if (JSObject *obj = static_cast<AutoObjectRooter *>(this)->obj)
|
||||
MarkObjectRoot(trc, obj, "JS::AutoObjectRooter.obj");
|
||||
MarkRoot(trc, obj, "JS::AutoObjectRooter.obj");
|
||||
return;
|
||||
|
||||
case ID:
|
||||
MarkIdRoot(trc, static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
|
||||
MarkRoot(trc, static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
|
||||
return;
|
||||
|
||||
case VALVECTOR: {
|
||||
AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
|
||||
MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case STRING:
|
||||
if (JSString *str = static_cast<AutoStringRooter *>(this)->str)
|
||||
MarkStringRoot(trc, str, "JS::AutoStringRooter.str");
|
||||
MarkRoot(trc, str, "JS::AutoStringRooter.str");
|
||||
return;
|
||||
|
||||
case IDVECTOR: {
|
||||
AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
|
||||
MarkIdRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
|
||||
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case SHAPEVECTOR: {
|
||||
AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
|
||||
MarkShapeRootRange(trc, vector.length(), const_cast<Shape **>(vector.begin()),
|
||||
"js::AutoShapeVector.vector");
|
||||
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case OBJVECTOR: {
|
||||
AutoObjectVector::VectorImpl &vector = static_cast<AutoObjectVector *>(this)->vector;
|
||||
MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
|
||||
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case VALARRAY: {
|
||||
AutoValueArray *array = static_cast<AutoValueArray *>(this);
|
||||
MarkValueRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
|
||||
MarkRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(tag >= 0);
|
||||
MarkValueRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
|
||||
"JS::AutoArrayRooter.array");
|
||||
MarkRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
|
||||
"JS::AutoArrayRooter.array");
|
||||
}
|
||||
|
||||
void
|
||||
@ -2048,9 +2049,9 @@ MarkContext(JSTracer *trc, JSContext *acx)
|
||||
|
||||
/* Mark other roots-by-definition in acx. */
|
||||
if (acx->globalObject && !acx->hasRunOption(JSOPTION_UNROOTED_GLOBAL))
|
||||
MarkObjectRoot(trc, acx->globalObject, "global object");
|
||||
MarkRoot(trc, acx->globalObject, "global object");
|
||||
if (acx->isExceptionPending())
|
||||
MarkValueRoot(trc, acx->getPendingException(), "exception");
|
||||
MarkRoot(trc, acx->getPendingException(), "exception");
|
||||
|
||||
if (acx->autoGCRooters)
|
||||
acx->autoGCRooters->traceAll(trc);
|
||||
@ -2058,7 +2059,7 @@ MarkContext(JSTracer *trc, JSContext *acx)
|
||||
if (acx->sharpObjectMap.depth > 0)
|
||||
js_TraceSharpMap(trc, &acx->sharpObjectMap);
|
||||
|
||||
MarkValueRoot(trc, acx->iterValue, "iterValue");
|
||||
MarkRoot(trc, acx->iterValue, "iterValue");
|
||||
}
|
||||
|
||||
void
|
||||
@ -2090,7 +2091,7 @@ MarkRuntime(JSTracer *trc)
|
||||
if (rt->scriptPCCounters) {
|
||||
const ScriptOpcodeCountsVector &vec = *rt->scriptPCCounters;
|
||||
for (size_t i = 0; i < vec.length(); i++)
|
||||
MarkScriptRoot(trc, vec[i].script, "scriptPCCounters");
|
||||
MarkRoot(trc, vec[i].script, "scriptPCCounters");
|
||||
}
|
||||
|
||||
js_TraceAtomState(trc);
|
||||
@ -2115,7 +2116,7 @@ MarkRuntime(JSTracer *trc)
|
||||
for (CellIterUnderGC i(c, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->pcCounters)
|
||||
MarkScriptRoot(trc, script, "profilingScripts");
|
||||
MarkRoot(trc, script, "profilingScripts");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,41 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jsgcmark.h"
|
||||
#include "jsprf.h"
|
||||
@ -72,13 +105,10 @@ PushMarkStack(GCMarker *gcmarker, JSString *thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing);
|
||||
|
||||
/*** Object Marking ***/
|
||||
|
||||
template<typename T>
|
||||
static inline void
|
||||
CheckMarkedThing(JSTracer *trc, T *thing)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(thing);
|
||||
JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
|
||||
JS_ASSERT_IF(trc->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc));
|
||||
@ -91,7 +121,7 @@ CheckMarkedThing(JSTracer *trc, T *thing)
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
MarkInternal(JSTracer *trc, T *thing)
|
||||
Mark(JSTracer *trc, T *thing)
|
||||
{
|
||||
CheckMarkedThing(trc, thing);
|
||||
|
||||
@ -118,241 +148,125 @@ MarkInternal(JSTracer *trc, T *thing)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define DeclMarkerImpl(base, type) \
|
||||
void \
|
||||
Mark##base(JSTracer *trc, const HeapPtr<type> &thing, const char *name) \
|
||||
{ \
|
||||
JS_SET_TRACING_NAME(trc, name); \
|
||||
MarkInternal(trc, thing.get()); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
Mark##base##Root(JSTracer *trc, type *thing, const char *name) \
|
||||
{ \
|
||||
JS_SET_TRACING_NAME(trc, name); \
|
||||
MarkInternal(trc, thing); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name) \
|
||||
{ \
|
||||
JS_SET_TRACING_NAME(trc, name); \
|
||||
MarkInternal(trc, thing); \
|
||||
} \
|
||||
\
|
||||
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name) \
|
||||
{ \
|
||||
for (size_t i = 0; i < len; ++i) { \
|
||||
JS_SET_TRACING_INDEX(trc, name, i); \
|
||||
MarkInternal(trc, vec[i].get()); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *name) \
|
||||
{ \
|
||||
for (size_t i = 0; i < len; ++i) { \
|
||||
JS_SET_TRACING_INDEX(trc, name, i); \
|
||||
MarkInternal(trc, vec[i]); \
|
||||
} \
|
||||
} \
|
||||
void
|
||||
MarkStringUnbarriered(JSTracer *trc, JSString *str, const char *name)
|
||||
{
|
||||
JS_ASSERT(str);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, str);
|
||||
}
|
||||
|
||||
void
|
||||
MarkString(JSTracer *trc, const MarkablePtr<JSString> &str, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, str.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(obj);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, obj);
|
||||
}
|
||||
|
||||
void
|
||||
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, obj.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkScriptUnbarriered(JSTracer *trc, JSScript *script, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(script);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, script);
|
||||
}
|
||||
|
||||
void
|
||||
MarkScript(JSTracer *trc, const MarkablePtr<JSScript> &script, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, script.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkShapeUnbarriered(JSTracer *trc, const Shape *shape, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(shape);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, shape);
|
||||
}
|
||||
|
||||
void
|
||||
MarkShape(JSTracer *trc, const MarkablePtr<const Shape> &shape, const char *name)
|
||||
{
|
||||
MarkShapeUnbarriered(trc, shape.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkBaseShapeUnbarriered(JSTracer *trc, BaseShape *base, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(base);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, base);
|
||||
}
|
||||
|
||||
void
|
||||
MarkBaseShape(JSTracer *trc, const MarkablePtr<BaseShape> &base, const char *name)
|
||||
{
|
||||
MarkBaseShapeUnbarriered(trc, base.value, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(type);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, type);
|
||||
}
|
||||
|
||||
void
|
||||
MarkTypeObject(JSTracer *trc, const MarkablePtr<types::TypeObject> &type, const char *name)
|
||||
{
|
||||
MarkTypeObjectUnbarriered(trc, type.value, name);
|
||||
}
|
||||
|
||||
DeclMarkerImpl(BaseShape, BaseShape)
|
||||
DeclMarkerImpl(Object, ArgumentsObject)
|
||||
DeclMarkerImpl(Object, GlobalObject)
|
||||
DeclMarkerImpl(Object, JSObject)
|
||||
DeclMarkerImpl(Object, JSFunction)
|
||||
DeclMarkerImpl(Script, JSScript)
|
||||
DeclMarkerImpl(Shape, Shape)
|
||||
DeclMarkerImpl(String, JSAtom)
|
||||
DeclMarkerImpl(String, JSString)
|
||||
DeclMarkerImpl(String, JSFlatString)
|
||||
DeclMarkerImpl(String, JSLinearString)
|
||||
DeclMarkerImpl(TypeObject, types::TypeObject)
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
DeclMarkerImpl(XML, JSXML)
|
||||
void
|
||||
MarkXMLUnbarriered(JSTracer *trc, JSXML *xml, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(xml);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
Mark(trc, xml);
|
||||
}
|
||||
|
||||
void
|
||||
MarkXML(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name)
|
||||
{
|
||||
MarkXMLUnbarriered(trc, xml.value, name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** Externally Typed Marking ***/
|
||||
#define JS_SAME_COMPARTMENT_ASSERT(thing1, thing2) \
|
||||
JS_ASSERT((thing1)->compartment() == (thing2)->compartment())
|
||||
|
||||
void
|
||||
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
JS_ASSERT(thing);
|
||||
JS_ASSERT(kind == GetGCThingTraceKind(thing));
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
MarkInternal(trc, reinterpret_cast<JSObject *>(thing));
|
||||
break;
|
||||
case JSTRACE_STRING:
|
||||
MarkInternal(trc, reinterpret_cast<JSString *>(thing));
|
||||
break;
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkInternal(trc, static_cast<JSScript *>(thing));
|
||||
break;
|
||||
case JSTRACE_SHAPE:
|
||||
MarkInternal(trc, reinterpret_cast<Shape *>(thing));
|
||||
break;
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkInternal(trc, reinterpret_cast<BaseShape *>(thing));
|
||||
break;
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
MarkInternal(trc, reinterpret_cast<types::TypeObject *>(thing));
|
||||
break;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case JSTRACE_XML:
|
||||
MarkInternal(trc, static_cast<JSXML *>(thing));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkGCThingRoot(JSTracer *trc, void *thing, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
if (!thing)
|
||||
return;
|
||||
MarkKind(trc, thing, GetGCThingTraceKind(thing));
|
||||
}
|
||||
|
||||
/*** ID Marking ***/
|
||||
|
||||
static inline void
|
||||
MarkIdInternal(JSTracer *trc, const jsid &id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
MarkInternal(trc, JSID_TO_STRING(id));
|
||||
else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
|
||||
MarkInternal(trc, JSID_TO_OBJECT(id));
|
||||
}
|
||||
|
||||
void
|
||||
MarkId(JSTracer *trc, const HeapId &id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkIdInternal(trc, id);
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRoot(JSTracer *trc, const jsid &id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkIdInternal(trc, id);
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkIdInternal(trc, vec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkIdInternal(trc, vec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Value Marking ***/
|
||||
|
||||
static inline void
|
||||
MarkValueInternal(JSTracer *trc, const Value &v)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
JS_ASSERT(v.toGCThing());
|
||||
return MarkKind(trc, v.toGCThing(), v.gcKind());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueInternal(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueRoot(JSTracer *trc, const Value &v, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueInternal(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkValueInternal(trc, vec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkValueInternal(trc, vec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Special Marking ***/
|
||||
|
||||
/*
|
||||
* The unioned HeapPtr stored in script->globalObj needs special treatment to
|
||||
* typecheck correctly.
|
||||
*/
|
||||
static void
|
||||
MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkInternal(trc, thing.get());
|
||||
}
|
||||
|
||||
void
|
||||
MarkShape(JSTracer *trc, const HeapPtr<const Shape> &thing, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkInternal(trc, const_cast<Shape *>(thing.get()));
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueInternal(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
MarkValue(trc, v, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Push Mark Stack ***/
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
|
||||
(thing)->compartment() == (rt)->gcCurrentCompartment);
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT_STR(rt, thing) \
|
||||
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
|
||||
#define JS_COMPARTMENT_ASSERT_STR(rt, thing) \
|
||||
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
|
||||
(thing)->compartment() == (rt)->gcCurrentCompartment || \
|
||||
(thing)->compartment() == (rt)->atomsCompartment);
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, JSXML *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -361,7 +275,7 @@ PushMarkStack(GCMarker *gcmarker, JSXML *thing)
|
||||
gcmarker->pushXML(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, JSObject *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -370,7 +284,7 @@ PushMarkStack(GCMarker *gcmarker, JSObject *thing)
|
||||
gcmarker->pushObject(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -379,7 +293,7 @@ PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
|
||||
gcmarker->pushObject(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -388,10 +302,7 @@ PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
|
||||
gcmarker->pushType(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkChildren(JSTracer *trc, JSScript *script);
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, JSScript *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -408,7 +319,7 @@ PushMarkStack(GCMarker *gcmarker, JSScript *thing)
|
||||
static void
|
||||
ScanShape(GCMarker *gcmarker, const Shape *shape);
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, const Shape *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -421,7 +332,7 @@ PushMarkStack(GCMarker *gcmarker, const Shape *thing)
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker *gcmarker, BaseShape *base);
|
||||
|
||||
static void
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
@ -431,6 +342,305 @@ PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
|
||||
ScanBaseShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkAtomRange(JSTracer *trc, size_t len, JSAtom **vec, const char *name)
|
||||
{
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (JSAtom *atom = vec[i]) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
Mark(trc, atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkObjectRange(JSTracer *trc, size_t len, HeapPtr<JSObject> *vec, const char *name)
|
||||
{
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (JSObject *obj = vec[i]) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
Mark(trc, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkXMLRange(JSTracer *trc, size_t len, HeapPtr<JSXML> *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (JSXML *xml = vec[i]) {
|
||||
JS_SET_TRACING_INDEX(trc, "xml_vector", i);
|
||||
Mark(trc, xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdUnbarriered(JSTracer *trc, jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
Mark(trc, JSID_TO_STRING(id));
|
||||
else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
|
||||
Mark(trc, JSID_TO_OBJECT(id));
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdUnbarriered(JSTracer *trc, jsid id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkIdUnbarriered(trc, id);
|
||||
}
|
||||
|
||||
void
|
||||
MarkId(JSTracer *trc, const HeapId &id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkIdUnbarriered(trc, id.get(), name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRangeUnbarriered(JSTracer *trc, jsid *beg, jsid *end, const char *name)
|
||||
{
|
||||
for (jsid *idp = beg; idp != end; ++idp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, (idp - beg));
|
||||
MarkIdUnbarriered(trc, *idp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRangeUnbarriered(JSTracer *trc, size_t len, jsid *vec, const char *name)
|
||||
{
|
||||
MarkIdRangeUnbarriered(trc, vec, vec + len, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkIdRange(JSTracer *trc, HeapId *beg, HeapId *end, const char *name)
|
||||
{
|
||||
for (HeapId *idp = beg; idp != end; ++idp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, (idp - beg));
|
||||
MarkIdUnbarriered(trc, *idp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
JS_ASSERT(thing);
|
||||
JS_ASSERT(kind == GetGCThingTraceKind(thing));
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
Mark(trc, reinterpret_cast<JSObject *>(thing));
|
||||
break;
|
||||
case JSTRACE_STRING:
|
||||
Mark(trc, reinterpret_cast<JSString *>(thing));
|
||||
break;
|
||||
case JSTRACE_SCRIPT:
|
||||
Mark(trc, static_cast<JSScript *>(thing));
|
||||
break;
|
||||
case JSTRACE_SHAPE:
|
||||
Mark(trc, reinterpret_cast<Shape *>(thing));
|
||||
break;
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
Mark(trc, reinterpret_cast<BaseShape *>(thing));
|
||||
break;
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
MarkTypeObjectUnbarriered(trc, reinterpret_cast<types::TypeObject *>(thing), "type_stack");
|
||||
break;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case JSTRACE_XML:
|
||||
Mark(trc, static_cast<JSXML *>(thing));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */
|
||||
void
|
||||
MarkValueRaw(JSTracer *trc, const js::Value &v)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
JS_ASSERT(v.toGCThing());
|
||||
return MarkKind(trc, v.toGCThing(), v.gcKind());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueRaw(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, v, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
MarkValue(trc, v, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, const HeapValue *beg, const HeapValue *end, const char *name)
|
||||
{
|
||||
for (const HeapValue *vp = beg; vp < end; ++vp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, vp - beg);
|
||||
MarkValueRaw(trc, vp->get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name)
|
||||
{
|
||||
MarkValueRange(trc, vec, vec + len, name);
|
||||
}
|
||||
|
||||
/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */
|
||||
void
|
||||
MarkGCThing(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
MarkKind(trc, thing, kind);
|
||||
}
|
||||
|
||||
void
|
||||
MarkGCThing(JSTracer *trc, void *thing)
|
||||
{
|
||||
if (!thing)
|
||||
return;
|
||||
MarkKind(trc, thing, GetGCThingTraceKind(thing));
|
||||
}
|
||||
|
||||
void
|
||||
MarkGCThing(JSTracer *trc, void *thing, const char *name, size_t index)
|
||||
{
|
||||
JS_SET_TRACING_INDEX(trc, name, index);
|
||||
MarkGCThing(trc, thing);
|
||||
}
|
||||
|
||||
void
|
||||
Mark(JSTracer *trc, void *thing, JSGCTraceKind kind, const char *name)
|
||||
{
|
||||
JS_ASSERT(thing);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkKind(trc, thing, kind);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSObject *thing, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSString *thing, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSScript *thing, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, const Shape *thing, const char *name)
|
||||
{
|
||||
MarkShapeUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, types::TypeObject *thing, const char *name)
|
||||
{
|
||||
MarkTypeObjectUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSXML *thing, const char *name)
|
||||
{
|
||||
MarkXMLUnbarriered(trc, thing, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, const Value &v, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, v, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, jsid id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkIdUnbarriered(trc, id);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootGCThing(JSTracer *trc, void *thing, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkGCThing(trc, thing);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, const Shape **vec, const char *name)
|
||||
{
|
||||
const Shape **end = vec + len;
|
||||
for (const Shape **sp = vec; sp < end; ++sp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, sp - vec);
|
||||
MarkShapeUnbarriered(trc, *sp, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, JSObject **vec, const char *name)
|
||||
{
|
||||
JSObject **end = vec + len;
|
||||
for (JSObject **sp = vec; sp < end; ++sp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, sp - vec);
|
||||
MarkObjectUnbarriered(trc, *sp, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, const Value *beg, const Value *end, const char *name)
|
||||
{
|
||||
for (const Value *vp = beg; vp < end; ++vp) {
|
||||
JS_SET_TRACING_INDEX(trc, name, vp - beg);
|
||||
MarkValueRaw(trc, *vp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name)
|
||||
{
|
||||
MarkRootRange(trc, vec, vec + len, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, jsid *beg, jsid *end, const char *name)
|
||||
{
|
||||
MarkIdRangeUnbarriered(trc, beg, end, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
|
||||
{
|
||||
MarkIdRangeUnbarriered(trc, len, vec, name);
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker *gcmarker, const Shape *shape)
|
||||
{
|
||||
@ -469,7 +679,7 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
|
||||
*/
|
||||
if (base->isOwned()) {
|
||||
UnownedBaseShape *unowned = base->baseUnowned();
|
||||
JS_ASSERT(base->compartment() == unowned->compartment());
|
||||
JS_SAME_COMPARTMENT_ASSERT(base, unowned);
|
||||
unowned->markIfUnmarked(gcmarker->getMarkColor());
|
||||
}
|
||||
}
|
||||
@ -605,12 +815,12 @@ MarkChildren(JSTracer *trc, JSObject *obj)
|
||||
uint32_t nslots = obj->slotSpan();
|
||||
for (uint32_t i = 0; i < nslots; i++) {
|
||||
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
|
||||
MarkValueInternal(trc, obj->nativeGetSlot(i));
|
||||
MarkValueRaw(trc, obj->nativeGetSlot(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSString *str)
|
||||
{
|
||||
/*
|
||||
@ -626,7 +836,8 @@ MarkChildren(JSTracer *trc, JSString *str)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSScript *script)
|
||||
{
|
||||
CheckScript(script, NULL);
|
||||
@ -634,7 +845,7 @@ MarkChildren(JSTracer *trc, JSScript *script)
|
||||
JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
|
||||
script->compartment() == trc->runtime->gcCheckCompartment);
|
||||
|
||||
MarkStringRootRange(trc, script->natoms, script->atoms, "atoms");
|
||||
MarkAtomRange(trc, script->natoms, script->atoms, "atoms");
|
||||
|
||||
if (JSScript::isValidOffset(script->objectsOffset)) {
|
||||
JSObjectArray *objarray = script->objects();
|
||||
@ -669,16 +880,16 @@ MarkChildren(JSTracer *trc, JSScript *script)
|
||||
script->markTrapClosures(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
MarkChildren(JSTracer *trc, const Shape *shape)
|
||||
{
|
||||
MarkBaseShapeUnbarriered(trc, shape->base(), "base");
|
||||
MarkId(trc, shape->maybePropid(), "propid");
|
||||
MarkIdUnbarriered(trc, shape->maybePropid(), "propid");
|
||||
if (shape->previous())
|
||||
MarkShape(trc, shape->previous(), "parent");
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline void
|
||||
MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
|
||||
{
|
||||
if (base->hasGetterObject())
|
||||
@ -687,7 +898,7 @@ MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
|
||||
MarkObjectUnbarriered(trc, base->setterObject(), "setter");
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
MarkChildren(JSTracer *trc, BaseShape *base)
|
||||
{
|
||||
MarkBaseShapeGetterSetter(trc, base);
|
||||
@ -741,7 +952,7 @@ MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape)
|
||||
JSObject *prevParent = NULL;
|
||||
do {
|
||||
MarkCycleCollectorChildren(trc, shape->base(), &prevParent);
|
||||
MarkId(trc, shape->maybePropid(), "propid");
|
||||
MarkIdUnbarriered(trc, shape->maybePropid(), "propid");
|
||||
shape = shape->previous();
|
||||
} while (shape);
|
||||
}
|
||||
@ -776,7 +987,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
|
||||
PushMarkStack(gcmarker, type->interpretedFunction);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
MarkChildren(JSTracer *trc, types::TypeObject *type)
|
||||
{
|
||||
if (!type->singleton) {
|
||||
@ -804,7 +1015,7 @@ MarkChildren(JSTracer *trc, types::TypeObject *type)
|
||||
}
|
||||
|
||||
#ifdef JS_HAS_XML_SUPPORT
|
||||
static void
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSXML *xml)
|
||||
{
|
||||
js_TraceXML(trc, xml);
|
||||
|
@ -1,8 +1,41 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jsgcmark_h___
|
||||
#define jsgcmark_h___
|
||||
@ -18,106 +51,72 @@
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
/*** Object Marking ***/
|
||||
|
||||
/*
|
||||
* These functions expose marking functionality for all of the different GC
|
||||
* thing kinds. For each GC thing, there are several variants. As an example,
|
||||
* these are the variants generated for JSObject. They are listed from most to
|
||||
* least desirable for use:
|
||||
*
|
||||
* MarkObject(JSTracer *trc, const HeapPtr<JSObject> &thing, const char *name);
|
||||
* This function should be used for marking JSObjects, in preference to all
|
||||
* others below. Use it when you have HeapPtr<JSObject>, which
|
||||
* automatically implements write barriers.
|
||||
*
|
||||
* MarkObjectRoot(JSTracer *trc, JSObject *thing, const char *name);
|
||||
* This function is only valid during the root marking phase of GC (i.e.,
|
||||
* when MarkRuntime is on the stack).
|
||||
*
|
||||
* MarkObjectUnbarriered(JSTracer *trc, JSObject *thing, const char *name);
|
||||
* Like MarkObject, this function can be called at any time. It is more
|
||||
* forgiving, since it doesn't demand a HeapPtr as an argument. Its use
|
||||
* should always be accompanied by a comment explaining how write barriers
|
||||
* are implemented for the given field.
|
||||
*
|
||||
* Additionally, the functions MarkObjectRange and MarkObjectRootRange are
|
||||
* defined for marking arrays of object pointers.
|
||||
*/
|
||||
#define DeclMarker(base, type) \
|
||||
void Mark##base(JSTracer *trc, const HeapPtr<type> &thing, const char *name); \
|
||||
void Mark##base##Root(JSTracer *trc, type *thing, const char *name); \
|
||||
void Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name); \
|
||||
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \
|
||||
void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name);
|
||||
|
||||
DeclMarker(BaseShape, BaseShape)
|
||||
DeclMarker(Object, ArgumentsObject)
|
||||
DeclMarker(Object, GlobalObject)
|
||||
DeclMarker(Object, JSObject)
|
||||
DeclMarker(Object, JSFunction)
|
||||
DeclMarker(Script, JSScript)
|
||||
DeclMarker(Shape, Shape)
|
||||
DeclMarker(String, JSAtom)
|
||||
DeclMarker(String, JSString)
|
||||
DeclMarker(String, JSFlatString)
|
||||
DeclMarker(String, JSLinearString)
|
||||
DeclMarker(TypeObject, types::TypeObject)
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
DeclMarker(XML, JSXML)
|
||||
#endif
|
||||
|
||||
/*** Externally Typed Marking ***/
|
||||
|
||||
/*
|
||||
* Note: this must only be called by the GC and only when we are tracing through
|
||||
* MarkRoots. It is explicitly for ConservativeStackMarking and should go away
|
||||
* after we transition to exact rooting.
|
||||
*/
|
||||
void
|
||||
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name);
|
||||
|
||||
void
|
||||
MarkGCThingRoot(JSTracer *trc, void *thing, const char *name);
|
||||
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name);
|
||||
|
||||
/*** ID Marking ***/
|
||||
void
|
||||
MarkStringUnbarriered(JSTracer *trc, JSString *str, const char *name);
|
||||
|
||||
void
|
||||
MarkString(JSTracer *trc, const MarkablePtr<JSString> &str, const char *name);
|
||||
|
||||
void
|
||||
MarkScriptUnbarriered(JSTracer *trc, JSScript *script, const char *name);
|
||||
|
||||
void
|
||||
MarkScript(JSTracer *trc, const MarkablePtr<JSScript> &script, const char *name);
|
||||
|
||||
void
|
||||
MarkShapeUnbarriered(JSTracer *trc, const Shape *shape, const char *name);
|
||||
|
||||
void
|
||||
MarkShape(JSTracer *trc, const MarkablePtr<const Shape> &shape, const char *name);
|
||||
|
||||
void
|
||||
MarkBaseShapeUnbarriered(JSTracer *trc, BaseShape *shape, const char *name);
|
||||
|
||||
void
|
||||
MarkTypeObjectUnbarriered(JSTracer *trc, types::TypeObject *type, const char *name);
|
||||
|
||||
void
|
||||
MarkTypeObject(JSTracer *trc, const MarkablePtr<types::TypeObject> &type, const char *name);
|
||||
|
||||
void
|
||||
MarkXMLUnbarriered(JSTracer *trc, JSXML *xml, const char *name);
|
||||
|
||||
void
|
||||
MarkXML(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name);
|
||||
|
||||
void
|
||||
MarkObjectRange(JSTracer *trc, size_t len, HeapPtr<JSObject> *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkXMLRange(JSTracer *trc, size_t len, HeapPtr<JSXML> *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkId(JSTracer *trc, const HeapId &id, const char *name);
|
||||
|
||||
void
|
||||
MarkIdRoot(JSTracer *trc, const jsid &id, const char *name);
|
||||
MarkIdRange(JSTracer *trc, js::HeapId *beg, js::HeapId *end, const char *name);
|
||||
|
||||
void
|
||||
MarkIdRange(JSTracer *trc, size_t len, js::HeapId *vec, const char *name);
|
||||
MarkIdRangeUnbarriered(JSTracer *trc, size_t len, jsid *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name);
|
||||
MarkIdRangeUnbarriered(JSTracer *trc, jsid *beg, jsid *end, const char *name);
|
||||
|
||||
/*** Value Marking ***/
|
||||
void
|
||||
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name);
|
||||
|
||||
void
|
||||
MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name);
|
||||
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkValueRoot(JSTracer *trc, const Value &v, const char *name);
|
||||
|
||||
void
|
||||
MarkValueRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name);
|
||||
|
||||
/*** Special Cases ***/
|
||||
|
||||
/* TypeNewObject contains a HeapPtr<const Shape> that needs a unique cast. */
|
||||
void
|
||||
MarkShape(JSTracer *trc, const HeapPtr<const Shape> &thing, const char *name);
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name);
|
||||
|
||||
/*
|
||||
* Mark a value that may be in a different compartment from the compartment
|
||||
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
|
||||
@ -125,28 +124,84 @@ MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name);
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name);
|
||||
|
||||
/*
|
||||
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
|
||||
* JSObject::TradeGuts. It should not be considered external interface.
|
||||
*/
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, const HeapValue *beg, const HeapValue *end, const char *name);
|
||||
|
||||
void
|
||||
MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSObject *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSString *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSScript *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, const Shape *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, types::TypeObject *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, JSXML *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, const Value &v, const char *name);
|
||||
|
||||
void
|
||||
MarkRoot(JSTracer *trc, jsid id, const char *name);
|
||||
|
||||
void
|
||||
MarkRootGCThing(JSTracer *trc, void *thing, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, const Shape **vec, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, JSObject **vec, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, const Value *beg, const Value *end, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, jsid *beg, jsid *end, const char *name);
|
||||
|
||||
void
|
||||
MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name);
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSObject *obj);
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSString *str);
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, const Shape *shape);
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSScript *script);
|
||||
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSXML *xml);
|
||||
|
||||
/*
|
||||
* Trace through the shape and any shapes it contains to mark
|
||||
* non-shape children. This is exposed to the JS API as
|
||||
* JS_TraceShapeCycleCollectorChildren.
|
||||
* non-shape children.
|
||||
*/
|
||||
void
|
||||
MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape);
|
||||
|
||||
/*** Generic ***/
|
||||
|
||||
/*
|
||||
* These Mark functions should only be called from templated code where it is
|
||||
* impossible to call one of the more specific functions.
|
||||
* Use function overloading to decide which function should be called based on
|
||||
* the type of the object. The static type is used at compile time to link to
|
||||
* the corresponding Mark/IsMarked function.
|
||||
*/
|
||||
|
||||
inline void
|
||||
Mark(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
{
|
||||
@ -154,13 +209,13 @@ Mark(JSTracer *trc, const js::HeapValue &v, const char *name)
|
||||
}
|
||||
|
||||
inline void
|
||||
Mark(JSTracer *trc, const HeapPtr<JSObject> &o, const char *name)
|
||||
Mark(JSTracer *trc, const MarkablePtr<JSObject> &o, const char *name)
|
||||
{
|
||||
MarkObject(trc, o, name);
|
||||
}
|
||||
|
||||
inline void
|
||||
Mark(JSTracer *trc, const HeapPtr<JSXML> &xml, const char *name)
|
||||
Mark(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name)
|
||||
{
|
||||
MarkXML(trc, xml, name);
|
||||
}
|
||||
@ -173,6 +228,12 @@ IsMarked(const js::Value &v)
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsMarked(JSObject *o)
|
||||
{
|
||||
return !IsAboutToBeFinalized(o);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsMarked(Cell *cell)
|
||||
{
|
||||
|
@ -1343,7 +1343,7 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
||||
JSCompartment *comp = newScript->fun->compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
MarkObjectUnbarriered(comp->barrierTracer(), newScript->fun, "write barrier");
|
||||
MarkShape(comp->barrierTracer(), newScript->shape, "write barrier");
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), newScript->shape, "write barrier");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap)
|
||||
static intN
|
||||
gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
MarkObjectRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry");
|
||||
MarkRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry");
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -771,7 +771,7 @@ struct Shape : public js::gc::Cell
|
||||
}
|
||||
|
||||
jsid propid() const { JS_ASSERT(!isEmptyShape()); return maybePropid(); }
|
||||
const HeapId &maybePropid() const { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
|
||||
jsid maybePropid() const { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
|
||||
|
||||
int16_t shortid() const { JS_ASSERT(hasShortID()); return maybeShortid(); }
|
||||
int16_t maybeShortid() const { return shortid_; }
|
||||
|
@ -395,7 +395,7 @@ Shape::writeBarrierPre(const js::Shape *shape)
|
||||
|
||||
JSCompartment *comp = shape->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "write barrier");
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), shape, "write barrier");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ Shape::readBarrier(const Shape *shape)
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JSCompartment *comp = shape->compartment();
|
||||
if (comp->needsBarrier())
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "read barrier");
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), shape, "read barrier");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -861,23 +861,18 @@ attr_identity(const JSXML *xmla, const JSXML *xmlb)
|
||||
return qname_identity(xmla->name, xmlb->name);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor)
|
||||
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<T> *cursor)
|
||||
{
|
||||
for (; cursor; cursor = cursor->next) {
|
||||
if (cursor->root)
|
||||
MarkXML(trc, (const HeapPtr<JSXML> &)cursor->root, "cursor_root");
|
||||
Mark(trc, (const MarkablePtr<T> &)cursor->root, "cursor_root");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor)
|
||||
{
|
||||
for (; cursor; cursor = cursor->next) {
|
||||
if (cursor->root)
|
||||
MarkObject(trc, (const HeapPtr<JSObject> &)cursor->root, "cursor_root");
|
||||
}
|
||||
}
|
||||
template void js_XMLArrayCursorTrace<JSXML>(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor);
|
||||
template void js_XMLArrayCursorTrace<JSObject>(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor);
|
||||
|
||||
template<class T>
|
||||
static HeapPtr<T> *
|
||||
|
@ -123,8 +123,9 @@ struct JSXMLArrayCursor
|
||||
}
|
||||
};
|
||||
|
||||
void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor);
|
||||
void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor);
|
||||
template<class T>
|
||||
void
|
||||
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<T> *cursor);
|
||||
|
||||
#define JSXML_PRESET_CAPACITY JS_BIT(31)
|
||||
#define JSXML_CAPACITY_MASK JS_BITMASK(31)
|
||||
|
Loading…
Reference in New Issue
Block a user