diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h new file mode 100644 index 000000000000..30551abc648e --- /dev/null +++ b/js/src/jscntxtinlines.h @@ -0,0 +1,155 @@ +/* -*- 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): + * Jeff Walden (original author) + * + * 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 jscntxtinlines_h___ +#define jscntxtinlines_h___ + +#include "jscntxt.h" +#include "jsxml.h" + +#include "jsobjinlines.h" + +namespace js { + +void +AutoIdArray::trace(JSTracer *trc) { + JS_ASSERT(tag == IDARRAY); + js::TraceValues(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray"); +} + +class AutoNamespaces : protected AutoGCRooter { + protected: + AutoNamespaces(JSContext *cx) : AutoGCRooter(cx, NAMESPACES) { + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + public: + JSXMLArray array; +}; + +inline void +AutoGCRooter::trace(JSTracer *trc) +{ + switch (tag) { + case JSVAL: + JS_SET_TRACING_NAME(trc, "js::AutoValueRooter.val"); + js_CallValueTracerIfGCThing(trc, static_cast(this)->val); + return; + + case SPROP: + static_cast(this)->sprop->trace(trc); + return; + + case WEAKROOTS: + static_cast(this)->savedRoots.mark(trc); + return; + + case COMPILER: +#if 0 /* JSCompiler is still old-style */ + static_cast(this)->trace(trc); +#else + JS_ASSERT(0); +#endif + return; + + case SCRIPT: + if (JSScript *script = static_cast(this)->script) + js_TraceScript(trc, script); + return; + + case ENUMERATOR: + static_cast(this)->trace(trc); + return; + + case IDARRAY: { + JSIdArray *ida = static_cast(this)->idArray; + TraceValues(trc, ida->length, ida->vector, "js::AutoIdArray.idArray"); + return; + } + + case DESCRIPTORS: { +#if 0 /* AutoDescriptorArray is still old-style */ + PropertyDescriptorArray &descriptors = + static_cast(this)->descriptors; + for (size_t i = 0, len = descriptors.length(); i < len; i++) { + PropertyDescriptor &desc = descriptors[i]; + + JS_CALL_VALUE_TRACER(trc, desc.value, "PropertyDescriptor::value"); + JS_CALL_VALUE_TRACER(trc, desc.get, "PropertyDescriptor::get"); + JS_CALL_VALUE_TRACER(trc, desc.set, "PropertyDescriptor::set"); + js_TraceId(trc, desc.id); + } +#else + JS_ASSERT(0); +#endif + return; + } + + case NAMESPACES: { + JSXMLArray &array = static_cast(this)->array; + TraceObjectVector(trc, reinterpret_cast(array.vector), array.length); + array.cursors->trace(trc); + return; + } + + case XML: + js_TraceXML(trc, static_cast(this)->xml); + return; + + case OBJECT: + if (JSObject *obj = static_cast(this)->obj) { + JS_SET_TRACING_NAME(trc, "js::AutoObjectRooter.obj"); + js_CallGCMarker(trc, obj, JSTRACE_OBJECT); + } + return; + + case ID: + JS_SET_TRACING_NAME(trc, "js::AutoIdRooter.val"); + js_CallValueTracerIfGCThing(trc, static_cast(this)->idval); + return; + } + + JS_ASSERT(tag >= 0); + TraceValues(trc, tag, static_cast(this)->array, "js::AutoArrayRooter.array"); +} + +} + +#endif /* jscntxtinlines_h___ */ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index bc4c46e17885..0446ff7a22fa 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -87,6 +87,7 @@ #include "jsdtracef.h" #endif +#include "jscntxtinlines.h" #include "jsobjinlines.h" /* @@ -2283,6 +2284,21 @@ gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, } \ JS_END_MACRO +namespace js { + +void +TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len) +{ + for (uint32 i = 0; i < len; i++) { + if (JSObject *obj = vec[i]) { + JS_SET_TRACING_INDEX(trc, "vector", i); + js_CallGCMarker(trc, obj, JSTRACE_OBJECT); + } + } +} + +} + void js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp) { @@ -2387,7 +2403,6 @@ JS_REQUIRES_STACK JS_FRIEND_API(void) js_TraceContext(JSTracer *trc, JSContext *acx) { JSStackHeader *sh; - JSTempValueRooter *tvr; /* * Trace active and suspended callstacks. @@ -2440,7 +2455,7 @@ js_TraceContext(JSTracer *trc, JSContext *acx) TRACE_JSVALS(trc, sh->nslots, JS_STACK_SEGMENT(sh), "stack"); } - for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) { + for (JSTempValueRooter *tvr = acx->tempValueRooters; tvr; tvr = tvr->down) { switch (tvr->count) { case JSTVU_SINGLE: JS_SET_TRACING_NAME(trc, "tvr->u.value"); @@ -2470,6 +2485,9 @@ js_TraceContext(JSTracer *trc, JSContext *acx) } } + for (js::AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down) + gcr->trace(trc); + if (acx->sharpObjectMap.depth > 0) js_TraceSharpMap(trc, &acx->sharpObjectMap); diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 8ec4f22554c9..d7726d8b960c 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -455,4 +455,23 @@ js_MarkTraps(JSTracer *trc); JS_END_EXTERN_C +namespace js { + +void +TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len); + +inline void +TraceValues(JSTracer *trc, size_t len, jsval *vec, const char *name) +{ + for (jsval *vp = vec, *end = vp + len; vp < end; vp++) { + jsval v = *vp; + if (JSVAL_IS_TRACEABLE(v)) { + JS_SET_TRACING_INDEX(trc, name, vp - vec); + js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); + } + } +} + +} + #endif /* jsgc_h___ */ diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 6d10212120a1..361f7e8ec3ad 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -868,60 +868,10 @@ attr_identity(const void *a, const void *b) return qname_identity(xmla->name, xmlb->name); } -struct JSXMLArrayCursor -{ - JSXMLArray *array; - uint32 index; - JSXMLArrayCursor *next; - JSXMLArrayCursor **prevp; - void *root; - - JSXMLArrayCursor(JSXMLArray *array) - : array(array), index(0), next(array->cursors), prevp(&array->cursors), - root(NULL) - { - if (next) - next->prevp = &next; - array->cursors = this; - } - - ~JSXMLArrayCursor() { disconnect(); } - - void disconnect() { - if (!array) - return; - if (next) - next->prevp = prevp; - *prevp = next; - array = NULL; - } - - void *getNext() { - if (!array || index >= array->length) - return NULL; - return root = array->vector[index++]; - } - - void *getCurrent() { - if (!array || index >= array->length) - return NULL; - return root = array->vector[index]; - } -}; - static void XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) { - void *root; -#ifdef DEBUG - size_t index = 0; -#endif - - for (; cursor; cursor = cursor->next) { - root = cursor->root; - JS_SET_TRACING_INDEX(trc, "cursor_root", index++); - js_CallValueTracerIfGCThing(trc, (jsval)root); - } + cursor->trace(trc); } /* NB: called with null cx from the GC, via xml_trace => XMLArrayTrim. */ @@ -5886,21 +5836,6 @@ typedef struct JSTempRootedNSArray { jsval value; /* extra root for temporaries */ } JSTempRootedNSArray; -static void -TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len) -{ - uint32 i; - JSObject *obj; - - for (i = 0; i < len; i++) { - obj = vec[i]; - if (obj) { - JS_SET_TRACING_INDEX(trc, "vector", i); - js_CallGCMarker(trc, obj, JSTRACE_OBJECT); - } - } -} - static void trace_temp_ns_array(JSTracer *trc, JSTempValueRooter *tvr) { diff --git a/js/src/jsxml.h b/js/src/jsxml.h index cb7198f59860..d5b20b0c881b 100644 --- a/js/src/jsxml.h +++ b/js/src/jsxml.h @@ -63,6 +63,58 @@ struct JSXMLArray { JSXMLArrayCursor *cursors; }; +struct JSXMLArrayCursor +{ + JSXMLArray *array; + uint32 index; + JSXMLArrayCursor *next; + JSXMLArrayCursor **prevp; + void *root; + + JSXMLArrayCursor(JSXMLArray *array) + : array(array), index(0), next(array->cursors), prevp(&array->cursors), + root(NULL) + { + if (next) + next->prevp = &next; + array->cursors = this; + } + + ~JSXMLArrayCursor() { disconnect(); } + + void disconnect() { + if (!array) + return; + if (next) + next->prevp = prevp; + *prevp = next; + array = NULL; + } + + void *getNext() { + if (!array || index >= array->length) + return NULL; + return root = array->vector[index++]; + } + + void *getCurrent() { + if (!array || index >= array->length) + return NULL; + return root = array->vector[index]; + } + + void trace(JSTracer *trc) { +#ifdef DEBUG + size_t index = 0; +#endif + for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) { + void *root = cursor->root; + JS_SET_TRACING_INDEX(trc, "cursor_root", index++); + js_CallValueTracerIfGCThing(trc, jsval(root)); + } + } +}; + #define JSXML_PRESET_CAPACITY JS_BIT(31) #define JSXML_CAPACITY_MASK JS_BITMASK(31) #define JSXML_CAPACITY(array) ((array)->capacity & JSXML_CAPACITY_MASK)