Bug 721463 - Clean up and minimize marking interfaces; r=billm

Currently, the marking interfaces are a giant pile of duplicated and,
frequently, unused code.  This patch reworks the interface to clean
up jsgcmark.h.
This commit is contained in:
Terrence Cole 2012-02-14 09:10:23 -08:00
parent 72d2af4861
commit 753ee85563
14 changed files with 439 additions and 668 deletions

View File

@ -257,7 +257,7 @@ Parser::trace(JSTracer *trc)
{
ObjectBox *objbox = traceListHead;
while (objbox) {
MarkRoot(trc, objbox->object, "parser.object");
MarkObjectRoot(trc, objbox->object, "parser.object");
if (objbox->isFunctionBox)
static_cast<FunctionBox *>(objbox)->bindings.trace(trc);
objbox = objbox->traceLink;

View File

@ -4291,7 +4291,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->vector, ida->vector + ida->length, "prop iter");
MarkIdRange(trc, ida->length, ida->vector, "prop iter");
}
}

View File

@ -386,16 +386,15 @@ js_TraceAtomState(JSTracer *trc)
JSAtomState *state = &rt->atomState;
if (rt->gcKeepAtoms) {
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront()) {
MarkRoot(trc, r.front().asPtr(), "locked_atom");
}
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront())
MarkStringRoot(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;
MarkRoot(trc, entry.asPtr(), "interned_atom");
MarkStringRoot(trc, entry.asPtr(), "interned_atom");
}
}
}

View File

@ -417,7 +417,7 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
JS_ASSERT(trc->runtime->gcCurrentCompartment);
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront())
MarkRoot(trc, e.front().key, "cross-compartment wrapper");
MarkValueRoot(trc, e.front().key, "cross-compartment wrapper");
}
void
@ -432,7 +432,7 @@ JSCompartment::markTypes(JSTracer *trc)
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
MarkRoot(trc, script, "mark_types_script");
MarkScriptRoot(trc, script, "mark_types_script");
}
for (size_t thingKind = FINALIZE_OBJECT0;
@ -441,12 +441,12 @@ JSCompartment::markTypes(JSTracer *trc)
for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) {
JSObject *object = i.get<JSObject>();
if (object->hasSingletonType())
MarkRoot(trc, object, "mark_types_singleton");
MarkObjectRoot(trc, object, "mark_types_singleton");
}
}
for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next())
MarkRoot(trc, i.get<types::TypeObject>(), "mark_types_scan");
MarkTypeObjectRoot(trc, i.get<types::TypeObject>(), "mark_types_scan");
}
void

View File

@ -1853,30 +1853,29 @@ 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)
MarkRootGCThing(trc, *reinterpret_cast<void **>(entry.key), name);
MarkGCThingRoot(trc, *reinterpret_cast<void **>(entry.key), name);
else
MarkRoot(trc, *reinterpret_cast<Value *>(entry.key), name);
MarkValueRoot(trc, *reinterpret_cast<Value *>(entry.key), name);
}
static void
gc_lock_traversal(const GCLocks::Entry &entry, JSTracer *trc)
{
JS_ASSERT(entry.value >= 1);
MarkRootGCThing(trc, entry.key, "locked object");
MarkGCThingRoot(trc, entry.key, "locked object");
}
void
AutoIdArray::trace(JSTracer *trc)
{
JS_ASSERT(tag == IDARRAY);
gc::MarkIdRange(trc, idArray->vector, idArray->vector + idArray->length,
"JSAutoIdArray.idArray");
gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
}
void
AutoEnumStateRooter::trace(JSTracer *trc)
{
gc::MarkRoot(trc, obj, "JS::AutoEnumStateRooter.obj");
gc::MarkObjectRoot(trc, obj, "JS::AutoEnumStateRooter.obj");
}
inline void
@ -1884,7 +1883,7 @@ AutoGCRooter::trace(JSTracer *trc)
{
switch (tag) {
case JSVAL:
MarkRoot(trc, static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
MarkValueRoot(trc, static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
return;
case PARSER:
@ -1897,7 +1896,7 @@ AutoGCRooter::trace(JSTracer *trc)
case IDARRAY: {
JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
MarkIdRange(trc, ida->vector, ida->vector + ida->length, "JS::AutoIdArray.idArray");
MarkIdRange(trc, ida->length, ida->vector, "JS::AutoIdArray.idArray");
return;
}
@ -1906,10 +1905,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];
MarkRoot(trc, desc.pd, "PropDesc::pd");
MarkRoot(trc, desc.value, "PropDesc::value");
MarkRoot(trc, desc.get, "PropDesc::get");
MarkRoot(trc, desc.set, "PropDesc::set");
MarkValueRoot(trc, desc.pd, "PropDesc::pd");
MarkValueRoot(trc, desc.value, "PropDesc::value");
MarkValueRoot(trc, desc.get, "PropDesc::get");
MarkValueRoot(trc, desc.set, "PropDesc::set");
}
return;
}
@ -1917,12 +1916,12 @@ AutoGCRooter::trace(JSTracer *trc)
case DESCRIPTOR : {
PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
if (desc.obj)
MarkRoot(trc, desc.obj, "Descriptor::obj");
MarkRoot(trc, desc.value, "Descriptor::value");
MarkObjectRoot(trc, desc.obj, "Descriptor::obj");
MarkValueRoot(trc, desc.value, "Descriptor::value");
if ((desc.attrs & JSPROP_GETTER) && desc.getter)
MarkRoot(trc, CastAsObject(desc.getter), "Descriptor::get");
MarkObjectRoot(trc, CastAsObject(desc.getter), "Descriptor::get");
if (desc.attrs & JSPROP_SETTER && desc.setter)
MarkRoot(trc, CastAsObject(desc.setter), "Descriptor::set");
MarkObjectRoot(trc, CastAsObject(desc.setter), "Descriptor::set");
return;
}
@ -1939,52 +1938,53 @@ AutoGCRooter::trace(JSTracer *trc)
case OBJECT:
if (JSObject *obj = static_cast<AutoObjectRooter *>(this)->obj)
MarkRoot(trc, obj, "JS::AutoObjectRooter.obj");
MarkObjectRoot(trc, obj, "JS::AutoObjectRooter.obj");
return;
case ID:
MarkRoot(trc, static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
MarkIdRoot(trc, static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
return;
case VALVECTOR: {
AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
return;
}
case STRING:
if (JSString *str = static_cast<AutoStringRooter *>(this)->str)
MarkRoot(trc, str, "JS::AutoStringRooter.str");
MarkStringRoot(trc, str, "JS::AutoStringRooter.str");
return;
case IDVECTOR: {
AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
MarkIdRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
return;
}
case SHAPEVECTOR: {
AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
MarkShapeRootRange(trc, vector.length(), const_cast<Shape **>(vector.begin()),
"js::AutoShapeVector.vector");
return;
}
case OBJVECTOR: {
AutoObjectVector::VectorImpl &vector = static_cast<AutoObjectVector *>(this)->vector;
MarkRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
return;
}
case VALARRAY: {
AutoValueArray *array = static_cast<AutoValueArray *>(this);
MarkRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
MarkValueRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
return;
}
}
JS_ASSERT(tag >= 0);
MarkRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
"JS::AutoArrayRooter.array");
MarkValueRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
"JS::AutoArrayRooter.array");
}
void
@ -2003,9 +2003,9 @@ MarkContext(JSTracer *trc, JSContext *acx)
/* Mark other roots-by-definition in acx. */
if (acx->globalObject && !acx->hasRunOption(JSOPTION_UNROOTED_GLOBAL))
MarkRoot(trc, acx->globalObject, "global object");
MarkObjectRoot(trc, acx->globalObject, "global object");
if (acx->isExceptionPending())
MarkRoot(trc, acx->getPendingException(), "exception");
MarkValueRoot(trc, acx->getPendingException(), "exception");
if (acx->autoGCRooters)
acx->autoGCRooters->traceAll(trc);
@ -2013,7 +2013,7 @@ MarkContext(JSTracer *trc, JSContext *acx)
if (acx->sharpObjectMap.depth > 0)
js_TraceSharpMap(trc, &acx->sharpObjectMap);
MarkRoot(trc, acx->iterValue, "iterValue");
MarkValueRoot(trc, acx->iterValue, "iterValue");
}
void
@ -2045,7 +2045,7 @@ MarkRuntime(JSTracer *trc)
if (rt->scriptPCCounters) {
const ScriptOpcodeCountsVector &vec = *rt->scriptPCCounters;
for (size_t i = 0; i < vec.length(); i++)
MarkRoot(trc, vec[i].script, "scriptPCCounters");
MarkScriptRoot(trc, vec[i].script, "scriptPCCounters");
}
js_TraceAtomState(trc);
@ -2070,7 +2070,7 @@ MarkRuntime(JSTracer *trc)
for (CellIterUnderGC i(c, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
if (script->pcCounters)
MarkRoot(trc, script, "profilingScripts");
MarkScriptRoot(trc, script, "profilingScripts");
}
}
}

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** 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 ***** */
*/
/* 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/. */
#include "jsgcmark.h"
#include "jsprf.h"
@ -105,10 +72,13 @@ 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));
@ -121,7 +91,7 @@ CheckMarkedThing(JSTracer *trc, T *thing)
template<typename T>
void
Mark(JSTracer *trc, T *thing)
MarkInternal(JSTracer *trc, T *thing)
{
CheckMarkedThing(trc, thing);
@ -148,125 +118,276 @@ Mark(JSTracer *trc, T *thing)
#endif
}
void
MarkStringUnbarriered(JSTracer *trc, JSString *str, const char *name)
template <typename T>
static void
MarkUnbarriered(JSTracer *trc, T *thing, const char *name)
{
JS_ASSERT(str);
JS_SET_TRACING_NAME(trc, name);
Mark(trc, str);
MarkInternal(trc, thing);
}
void
MarkString(JSTracer *trc, const MarkablePtr<JSString> &str, const char *name)
template <typename T>
static void
Mark(JSTracer *trc, const HeapPtr<T> &thing, 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);
MarkInternal(trc, thing.get());
}
void
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name)
template <typename T>
static void
MarkRoot(JSTracer *trc, T *thing, 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);
MarkInternal(trc, thing);
}
void
MarkScript(JSTracer *trc, const MarkablePtr<JSScript> &script, const char *name)
{
MarkScriptUnbarriered(trc, script.value, name);
template <typename T>
static void
MarkRange(JSTracer *trc, size_t len, HeapPtr<T> *vec, const char *name) {
for (size_t i = 0; i < len; ++i) {
if (T *obj = vec[i]) {
JS_SET_TRACING_INDEX(trc, name, i);
MarkInternal(trc, obj);
}
}
}
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);
template <typename T>
static void
MarkRootRange(JSTracer *trc, size_t len, T **vec, const char *name) {
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
MarkInternal(trc, vec[i]);
}
}
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);
}
#define DeclMarkerImpl(base, type) \
void \
Mark##base(JSTracer *trc, const HeapPtr<type> &thing, const char *name) \
{ \
Mark<type>(trc, thing, name); \
} \
\
void \
Mark##base##Root(JSTracer *trc, type *thing, const char *name) \
{ \
MarkRoot<type>(trc, thing, name); \
} \
\
void \
Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name) \
{ \
MarkUnbarriered<type>(trc, thing, name); \
} \
\
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name) \
{ \
MarkRange<type>(trc, len, vec, name); \
} \
\
void Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *name) \
{ \
MarkRootRange<type>(trc, len, vec, 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
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);
}
DeclMarkerImpl(XML, JSXML)
#endif
#define JS_SAME_COMPARTMENT_ASSERT(thing1, thing2) \
JS_ASSERT((thing1)->compartment() == (thing2)->compartment())
/*** Externally Typed Marking ***/
#define JS_COMPARTMENT_ASSERT(rt, thing) \
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
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, \
(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);
void
static void
PushMarkStack(GCMarker *gcmarker, JSXML *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -275,7 +396,7 @@ PushMarkStack(GCMarker *gcmarker, JSXML *thing)
gcmarker->pushXML(thing);
}
void
static void
PushMarkStack(GCMarker *gcmarker, JSObject *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -284,7 +405,7 @@ PushMarkStack(GCMarker *gcmarker, JSObject *thing)
gcmarker->pushObject(thing);
}
void
static void
PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -293,7 +414,7 @@ PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
gcmarker->pushObject(thing);
}
void
static void
PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -302,7 +423,10 @@ PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
gcmarker->pushType(thing);
}
void
static void
MarkChildren(JSTracer *trc, JSScript *script);
static void
PushMarkStack(GCMarker *gcmarker, JSScript *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -319,7 +443,7 @@ PushMarkStack(GCMarker *gcmarker, JSScript *thing)
static void
ScanShape(GCMarker *gcmarker, const Shape *shape);
void
static void
PushMarkStack(GCMarker *gcmarker, const Shape *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -332,7 +456,7 @@ PushMarkStack(GCMarker *gcmarker, const Shape *thing)
static inline void
ScanBaseShape(GCMarker *gcmarker, BaseShape *base);
void
static void
PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -342,305 +466,6 @@ 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)
{
@ -679,7 +504,7 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
*/
if (base->isOwned()) {
UnownedBaseShape *unowned = base->baseUnowned();
JS_SAME_COMPARTMENT_ASSERT(base, unowned);
JS_ASSERT(base->compartment() == unowned->compartment());
unowned->markIfUnmarked(gcmarker->getMarkColor());
}
}
@ -815,12 +640,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);
MarkValueRaw(trc, obj->nativeGetSlot(i));
MarkValueInternal(trc, obj->nativeGetSlot(i));
}
}
}
void
static void
MarkChildren(JSTracer *trc, JSString *str)
{
/*
@ -836,8 +661,7 @@ MarkChildren(JSTracer *trc, JSString *str)
}
}
void
static void
MarkChildren(JSTracer *trc, JSScript *script)
{
CheckScript(script, NULL);
@ -845,7 +669,7 @@ MarkChildren(JSTracer *trc, JSScript *script)
JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
script->compartment() == trc->runtime->gcCheckCompartment);
MarkAtomRange(trc, script->natoms, script->atoms, "atoms");
MarkStringRootRange(trc, script->natoms, script->atoms, "atoms");
if (JSScript::isValidOffset(script->objectsOffset)) {
JSObjectArray *objarray = script->objects();
@ -880,16 +704,16 @@ MarkChildren(JSTracer *trc, JSScript *script)
script->markTrapClosures(trc);
}
void
static void
MarkChildren(JSTracer *trc, const Shape *shape)
{
MarkBaseShapeUnbarriered(trc, shape->base(), "base");
MarkIdUnbarriered(trc, shape->maybePropid(), "propid");
MarkId(trc, shape->maybePropid(), "propid");
if (shape->previous())
MarkShape(trc, shape->previous(), "parent");
}
inline void
static inline void
MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
{
if (base->hasGetterObject())
@ -898,7 +722,7 @@ MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
MarkObjectUnbarriered(trc, base->setterObject(), "setter");
}
void
static void
MarkChildren(JSTracer *trc, BaseShape *base)
{
MarkBaseShapeGetterSetter(trc, base);
@ -952,7 +776,7 @@ MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape)
JSObject *prevParent = NULL;
do {
MarkCycleCollectorChildren(trc, shape->base(), &prevParent);
MarkIdUnbarriered(trc, shape->maybePropid(), "propid");
MarkId(trc, shape->maybePropid(), "propid");
shape = shape->previous();
} while (shape);
}
@ -987,7 +811,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
PushMarkStack(gcmarker, type->interpretedFunction);
}
void
static void
MarkChildren(JSTracer *trc, types::TypeObject *type)
{
if (!type->singleton) {
@ -1015,7 +839,7 @@ MarkChildren(JSTracer *trc, types::TypeObject *type)
}
#ifdef JS_HAS_XML_SUPPORT
void
static void
MarkChildren(JSTracer *trc, JSXML *xml)
{
js_TraceXML(trc, xml);

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** 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 ***** */
*/
/* 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/. */
#ifndef jsgcmark_h___
#define jsgcmark_h___
@ -51,72 +18,112 @@
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
MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name);
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind);
void
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name);
MarkGCThingRoot(JSTracer *trc, void *thing, const char *name);
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);
/*** ID Marking ***/
void
MarkId(JSTracer *trc, const HeapId &id, const char *name);
void
MarkIdRange(JSTracer *trc, js::HeapId *beg, js::HeapId *end, const char *name);
MarkIdRoot(JSTracer *trc, const jsid &id, const char *name);
void
MarkIdRangeUnbarriered(JSTracer *trc, size_t len, jsid *vec, const char *name);
MarkIdRange(JSTracer *trc, size_t len, js::HeapId *vec, const char *name);
void
MarkIdRangeUnbarriered(JSTracer *trc, jsid *beg, jsid *end, const char *name);
MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name);
void
MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind);
void
MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name);
/*** Value Marking ***/
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);
inline void
MarkValueRootRange(JSTracer *trc, const Value *begin, const Value *end, const char *name)
{
MarkValueRootRange(trc, end - begin, begin, 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.)
@ -124,84 +131,27 @@ MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name);
void
MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name);
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);
/*
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
* JSObject::TradeGuts. It should not be considered external interface.
*/
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.
* non-shape children. This is exposed to the JS API as
* JS_TraceShapeCycleCollectorChildren.
*/
void
MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape);
/*** Generic ***/
/*
* 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.
* The Mark() functions interface should only be used by code that must be
* templated. Other uses should use the more specific, type-named functions.
*/
inline void
Mark(JSTracer *trc, const js::HeapValue &v, const char *name)
{
@ -209,13 +159,13 @@ Mark(JSTracer *trc, const js::HeapValue &v, const char *name)
}
inline void
Mark(JSTracer *trc, const MarkablePtr<JSObject> &o, const char *name)
Mark(JSTracer *trc, const HeapPtr<JSObject> &o, const char *name)
{
MarkObject(trc, o, name);
}
inline void
Mark(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name)
Mark(JSTracer *trc, const HeapPtr<JSXML> &xml, const char *name)
{
MarkXML(trc, xml, name);
}
@ -228,12 +178,6 @@ IsMarked(const js::Value &v)
return true;
}
inline bool
IsMarked(JSObject *o)
{
return !IsAboutToBeFinalized(o);
}
inline bool
IsMarked(Cell *cell)
{

View File

@ -1343,7 +1343,7 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
JSCompartment *comp = newScript->fun->compartment();
if (comp->needsBarrier()) {
MarkObjectUnbarriered(comp->barrierTracer(), newScript->fun, "write barrier");
MarkShapeUnbarriered(comp->barrierTracer(), newScript->shape, "write barrier");
MarkShape(comp->barrierTracer(), newScript->shape, "write barrier");
}
#endif
}

View File

@ -417,7 +417,7 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap)
static intN
gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg)
{
MarkRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry");
MarkObjectRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry");
return JS_DHASH_NEXT;
}

View File

@ -771,7 +771,7 @@ struct Shape : public js::gc::Cell
}
jsid propid() const { JS_ASSERT(!isEmptyShape()); return maybePropid(); }
jsid maybePropid() const { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
const HeapId &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_; }

View File

@ -395,7 +395,7 @@ Shape::writeBarrierPre(const js::Shape *shape)
JSCompartment *comp = shape->compartment();
if (comp->needsBarrier())
MarkShapeUnbarriered(comp->barrierTracer(), shape, "write barrier");
MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(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(), shape, "read barrier");
MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "read barrier");
#endif
}

View File

@ -861,18 +861,23 @@ attr_identity(const JSXML *xmla, const JSXML *xmlb)
return qname_identity(xmla->name, xmlb->name);
}
template<class T>
void
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<T> *cursor)
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor)
{
for (; cursor; cursor = cursor->next) {
if (cursor->root)
Mark(trc, (const MarkablePtr<T> &)cursor->root, "cursor_root");
MarkXML(trc, (const HeapPtr<JSXML> &)cursor->root, "cursor_root");
}
}
template void js_XMLArrayCursorTrace<JSXML>(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor);
template void js_XMLArrayCursorTrace<JSObject>(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor);
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<class T>
static HeapPtr<T> *

View File

@ -123,9 +123,8 @@ struct JSXMLArrayCursor
}
};
template<class T>
void
js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<T> *cursor);
void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSXML> *cursor);
void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor);
#define JSXML_PRESET_CAPACITY JS_BIT(31)
#define JSXML_CAPACITY_MASK JS_BITMASK(31)

View File

@ -455,7 +455,7 @@ StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbyt
if (!fp->isScriptFrame()) {
JS_ASSERT(fp->isDummyFrame());
gc::MarkRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
gc::MarkValueRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
return;
}
@ -464,7 +464,7 @@ StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbyt
JSScript *script = fp->script();
if (!script->hasAnalysis() || !script->analysis()->ranLifetimes()) {
gc::MarkRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
gc::MarkValueRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
return;
}
@ -485,12 +485,12 @@ StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbyt
/* Will this slot be synced by the JIT? */
if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset))
gc::MarkRoot(trc, *vp, "vm_stack");
gc::MarkValueRoot(trc, *vp, "vm_stack");
else
*vp = UndefinedValue();
}
gc::MarkRootRange(trc, fixedEnd, slotsEnd, "vm_stack");
gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack");
}
void
@ -527,7 +527,7 @@ StackSpace::mark(JSTracer *trc)
pc = fp->prevpc(&site);
JS_ASSERT_IF(fp->prev(), !site);
}
gc::MarkRootRange(trc, seg->slotsBegin(), slotsEnd, "vm_stack");
gc::MarkValueRootRange(trc, seg->slotsBegin(), slotsEnd, "vm_stack");
nextSegEnd = (Value *)seg;
}
}