mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 910771 (part 1) - Create js/Tracer.h and gc/Tracer.cpp. r=terrence.
This commit is contained in:
parent
5c8c4e7794
commit
8b1341d991
@ -13,6 +13,7 @@
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/dom/HTMLPropertiesCollectionBinding.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/Tracer.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/scache/StartupCache.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/Tracer.h"
|
||||
|
||||
inline JSObject*
|
||||
nsWrapperCache::GetWrapper() const
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Tracer.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/Util.h" // for Maybe
|
||||
|
@ -7,8 +7,9 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/Vector.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/Tracer.h"
|
||||
#include "js/Vector.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
|
||||
|
@ -292,11 +292,6 @@ typedef bool
|
||||
typedef void
|
||||
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
|
||||
|
||||
// Callback that JSTraceOp implementation can provide to return a string
|
||||
// describing the reference traced with JS_CallTracer.
|
||||
typedef void
|
||||
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
|
||||
|
||||
// A generic type for functions mapping an object to another object, or null
|
||||
// if an error or exception was thrown on cx.
|
||||
typedef JSObject *
|
||||
|
191
js/public/Tracer.h
Normal file
191
js/public/Tracer.h
Normal file
@ -0,0 +1,191 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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 js_Tracer_h
|
||||
#define js_Tracer_h
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
struct JSTracer;
|
||||
|
||||
namespace JS {
|
||||
template <typename T> class Heap;
|
||||
template <typename T> class TenuredHeap;
|
||||
}
|
||||
|
||||
// Tracer callback, called for each traceable thing directly referenced by a
|
||||
// particular object or runtime structure. It is the callback responsibility
|
||||
// to ensure the traversal of the full object graph via calling eventually
|
||||
// JS_TraceChildren on the passed thing. In this case the callback must be
|
||||
// prepared to deal with cycles in the traversal graph.
|
||||
//
|
||||
// kind argument is one of JSTRACE_OBJECT, JSTRACE_STRING or a tag denoting
|
||||
// internal implementation-specific traversal kind. In the latter case the only
|
||||
// operations on thing that the callback can do is to call JS_TraceChildren or
|
||||
// JS_GetTraceThingInfo.
|
||||
//
|
||||
// If eagerlyTraceWeakMaps is true, when we trace a WeakMap visit all
|
||||
// of its mappings. This should be used in cases where the tracer
|
||||
// wants to use the existing liveness of entries.
|
||||
typedef void
|
||||
(* JSTraceCallback)(JSTracer *trc, void **thingp, JSGCTraceKind kind);
|
||||
|
||||
// Callback that JSTraceOp implementation can provide to return a string
|
||||
// describing the reference traced with JS_CallTracer.
|
||||
typedef void
|
||||
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
|
||||
|
||||
enum WeakMapTraceKind {
|
||||
DoNotTraceWeakMaps = 0,
|
||||
TraceWeakMapValues = 1,
|
||||
TraceWeakMapKeysValues = 2
|
||||
};
|
||||
|
||||
struct JSTracer {
|
||||
JSRuntime *runtime;
|
||||
JSTraceCallback callback;
|
||||
JSTraceNamePrinter debugPrinter;
|
||||
const void *debugPrintArg;
|
||||
size_t debugPrintIndex;
|
||||
WeakMapTraceKind eagerlyTraceWeakMaps;
|
||||
#ifdef JS_GC_ZEAL
|
||||
void *realLocation;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Set debugging information about a reference to a traceable thing to prepare
|
||||
// for the following call to JS_CallTracer.
|
||||
//
|
||||
// When printer is null, arg must be const char * or char * C string naming
|
||||
// the reference and index must be either (size_t)-1 indicating that the name
|
||||
// alone describes the reference or it must be an index into some array vector
|
||||
// that stores the reference.
|
||||
//
|
||||
// When printer callback is not null, the arg and index arguments are
|
||||
// available to the callback as debugPrintArg and debugPrintIndex fields
|
||||
// of JSTracer.
|
||||
//
|
||||
// The storage for name or callback's arguments needs to live only until
|
||||
// the following call to JS_CallTracer returns.
|
||||
//
|
||||
# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
|
||||
JS_BEGIN_MACRO \
|
||||
(trc)->debugPrinter = (printer); \
|
||||
(trc)->debugPrintArg = (arg); \
|
||||
(trc)->debugPrintIndex = (index); \
|
||||
JS_END_MACRO
|
||||
|
||||
// Sets the real location for a marked reference, when passing the address
|
||||
// directly is not feasable.
|
||||
//
|
||||
// FIXME: This is currently overcomplicated by our need to nest calls for Values
|
||||
// stored as keys in hash tables, but will get simplified once we can rekey
|
||||
// in-place.
|
||||
//
|
||||
#ifdef JS_GC_ZEAL
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!(trc)->realLocation || !(location)) \
|
||||
(trc)->realLocation = (location); \
|
||||
JS_END_MACRO
|
||||
# define JS_UNSET_TRACING_LOCATION(trc) \
|
||||
JS_BEGIN_MACRO \
|
||||
(trc)->realLocation = NULL; \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_END_MACRO
|
||||
# define JS_UNSET_TRACING_LOCATION(trc) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
// Convenience macro to describe the argument of JS_CallTracer using C string
|
||||
// and index.
|
||||
# define JS_SET_TRACING_INDEX(trc, name, index) \
|
||||
JS_SET_TRACING_DETAILS(trc, NULL, name, index)
|
||||
|
||||
// Convenience macro to describe the argument of JS_CallTracer using C string.
|
||||
# define JS_SET_TRACING_NAME(trc, name) \
|
||||
JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1)
|
||||
|
||||
// The JS_Call*Tracer family of functions traces the given GC thing reference.
|
||||
// This performs the tracing action configured on the given JSTracer:
|
||||
// typically calling the JSTracer::callback or marking the thing as live.
|
||||
//
|
||||
// The argument to JS_Call*Tracer is an in-out param: when the function
|
||||
// returns, the garbage collector might have moved the GC thing. In this case,
|
||||
// the reference passed to JS_Call*Tracer will be updated to the object's new
|
||||
// location. Callers of this method are responsible for updating any state
|
||||
// that is dependent on the object's address. For example, if the object's
|
||||
// address is used as a key in a hashtable, then the object must be removed
|
||||
// and re-inserted with the correct hash.
|
||||
//
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name);
|
||||
|
||||
template <typename HashSetEnum>
|
||||
inline void
|
||||
JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name)
|
||||
{
|
||||
JSObject *updated = key;
|
||||
JS_SET_TRACING_LOCATION(trc, reinterpret_cast<void *>(&const_cast<JSObject *&>(key)));
|
||||
JS_CallObjectTracer(trc, &updated, name);
|
||||
if (updated != key)
|
||||
e.rekeyFront(key, updated);
|
||||
}
|
||||
|
||||
// Trace an object that is known to always be tenured. No post barriers are
|
||||
// required in this case.
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name);
|
||||
|
||||
// API for JSTraceCallback implementations.
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceRuntime(JSTracer *trc);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
|
||||
void *thing, JSGCTraceKind kind, bool includeDetails);
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize);
|
||||
|
||||
#endif /* js_Tracer_h */
|
258
js/src/gc/Tracer.cpp
Normal file
258
js/src/gc/Tracer.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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 "js/Tracer.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsscript.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "gc/Marking.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallValueTracer(JSTracer *trc, Value *valuep, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, valuep, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name)
|
||||
{
|
||||
MarkIdUnbarriered(trc, idp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, objp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, strp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, scriptp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, valuep->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name)
|
||||
{
|
||||
MarkIdUnbarriered(trc, idp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, objp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, strp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, scriptp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name)
|
||||
{
|
||||
JSObject *obj = objp->getPtr();
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
JS_SET_TRACING_LOCATION(trc, (void*)objp);
|
||||
MarkObjectUnbarriered(trc, &obj, name);
|
||||
|
||||
objp->setPtr(obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
|
||||
{
|
||||
InitTracer(trc, rt, callback);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
js::TraceChildren(trc, thing, kind);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceRuntime(JSTracer *trc)
|
||||
{
|
||||
AssertHeapIsIdle(trc->runtime);
|
||||
TraceRuntime(trc);
|
||||
}
|
||||
|
||||
static size_t
|
||||
CountDecimalDigits(size_t num)
|
||||
{
|
||||
size_t numDigits = 0;
|
||||
do {
|
||||
num /= 10;
|
||||
numDigits++;
|
||||
} while (num > 0);
|
||||
|
||||
return numDigits;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
JSGCTraceKind kind, bool details)
|
||||
{
|
||||
const char *name = NULL; /* silence uninitialized warning */
|
||||
size_t n;
|
||||
|
||||
if (bufsize == 0)
|
||||
return;
|
||||
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
{
|
||||
name = static_cast<JSObject *>(thing)->getClass()->name;
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
name = ((JSString *)thing)->isDependent()
|
||||
? "substring"
|
||||
: "string";
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
name = "script";
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
name = "lazyscript";
|
||||
break;
|
||||
|
||||
case JSTRACE_IONCODE:
|
||||
name = "ioncode";
|
||||
break;
|
||||
|
||||
case JSTRACE_SHAPE:
|
||||
name = "shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
name = "base_shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
name = "type_object";
|
||||
break;
|
||||
}
|
||||
|
||||
n = strlen(name);
|
||||
if (n > bufsize - 1)
|
||||
n = bufsize - 1;
|
||||
js_memcpy(buf, name, n + 1);
|
||||
buf += n;
|
||||
bufsize -= n;
|
||||
*buf = '\0';
|
||||
|
||||
if (details && bufsize > 2) {
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
{
|
||||
JSObject *obj = (JSObject *)thing;
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
if (fun->displayAtom()) {
|
||||
*buf++ = ' ';
|
||||
bufsize--;
|
||||
PutEscapedString(buf, bufsize, fun->displayAtom(), 0);
|
||||
}
|
||||
} else if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) {
|
||||
JS_snprintf(buf, bufsize, " %p", obj->getPrivate());
|
||||
} else {
|
||||
JS_snprintf(buf, bufsize, " <no private>");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
{
|
||||
*buf++ = ' ';
|
||||
bufsize--;
|
||||
JSString *str = (JSString *)thing;
|
||||
|
||||
if (str->isLinear()) {
|
||||
bool willFit = str->length() + strlen("<length > ") +
|
||||
CountDecimalDigits(str->length()) < bufsize;
|
||||
|
||||
n = JS_snprintf(buf, bufsize, "<length %d%s> ",
|
||||
(int)str->length(),
|
||||
willFit ? "" : " (truncated)");
|
||||
buf += n;
|
||||
bufsize -= n;
|
||||
|
||||
PutEscapedString(buf, bufsize, &str->asLinear(), 0);
|
||||
}
|
||||
else
|
||||
JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno));
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
case JSTRACE_IONCODE:
|
||||
case JSTRACE_SHAPE:
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[bufsize - 1] = '\0';
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize)
|
||||
{
|
||||
if (trc->debugPrinter) {
|
||||
trc->debugPrinter(trc, buffer, bufferSize);
|
||||
return buffer;
|
||||
}
|
||||
if (trc->debugPrintIndex != (size_t) - 1) {
|
||||
JS_snprintf(buffer, bufferSize, "%s[%lu]",
|
||||
(const char *)trc->debugPrintArg,
|
||||
trc->debugPrintIndex);
|
||||
return buffer;
|
||||
}
|
||||
return (const char*)trc->debugPrintArg;
|
||||
}
|
||||
|
||||
|
237
js/src/jsapi.cpp
237
js/src/jsapi.cpp
@ -1901,243 +1901,6 @@ JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallValueTracer(JSTracer *trc, Value *valuep, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, valuep, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name)
|
||||
{
|
||||
MarkIdUnbarriered(trc, idp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, objp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name)
|
||||
{
|
||||
JSObject *obj = objp->getPtr();
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
JS_SET_TRACING_LOCATION(trc, (void*)objp);
|
||||
MarkObjectUnbarriered(trc, &obj, name);
|
||||
|
||||
objp->setPtr(obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, strp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, scriptp, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name)
|
||||
{
|
||||
MarkValueUnbarriered(trc, valuep->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name)
|
||||
{
|
||||
MarkIdUnbarriered(trc, idp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name)
|
||||
{
|
||||
MarkObjectUnbarriered(trc, objp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name)
|
||||
{
|
||||
MarkStringUnbarriered(trc, strp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name)
|
||||
{
|
||||
MarkScriptUnbarriered(trc, scriptp->unsafeGet(), name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
|
||||
{
|
||||
InitTracer(trc, rt, callback);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceRuntime(JSTracer *trc)
|
||||
{
|
||||
AssertHeapIsIdle(trc->runtime);
|
||||
TraceRuntime(trc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
js::TraceChildren(trc, thing, kind);
|
||||
}
|
||||
|
||||
static size_t
|
||||
CountDecimalDigits(size_t num)
|
||||
{
|
||||
size_t numDigits = 0;
|
||||
do {
|
||||
num /= 10;
|
||||
numDigits++;
|
||||
} while (num > 0);
|
||||
|
||||
return numDigits;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
JSGCTraceKind kind, bool details)
|
||||
{
|
||||
const char *name = NULL; /* silence uninitialized warning */
|
||||
size_t n;
|
||||
|
||||
if (bufsize == 0)
|
||||
return;
|
||||
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
{
|
||||
name = static_cast<JSObject *>(thing)->getClass()->name;
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
name = ((JSString *)thing)->isDependent()
|
||||
? "substring"
|
||||
: "string";
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
name = "script";
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
name = "lazyscript";
|
||||
break;
|
||||
|
||||
case JSTRACE_IONCODE:
|
||||
name = "ioncode";
|
||||
break;
|
||||
|
||||
case JSTRACE_SHAPE:
|
||||
name = "shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
name = "base_shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
name = "type_object";
|
||||
break;
|
||||
}
|
||||
|
||||
n = strlen(name);
|
||||
if (n > bufsize - 1)
|
||||
n = bufsize - 1;
|
||||
js_memcpy(buf, name, n + 1);
|
||||
buf += n;
|
||||
bufsize -= n;
|
||||
*buf = '\0';
|
||||
|
||||
if (details && bufsize > 2) {
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
{
|
||||
JSObject *obj = (JSObject *)thing;
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
if (fun->displayAtom()) {
|
||||
*buf++ = ' ';
|
||||
bufsize--;
|
||||
PutEscapedString(buf, bufsize, fun->displayAtom(), 0);
|
||||
}
|
||||
} else if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) {
|
||||
JS_snprintf(buf, bufsize, " %p", obj->getPrivate());
|
||||
} else {
|
||||
JS_snprintf(buf, bufsize, " <no private>");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
{
|
||||
*buf++ = ' ';
|
||||
bufsize--;
|
||||
JSString *str = (JSString *)thing;
|
||||
|
||||
if (str->isLinear()) {
|
||||
bool willFit = str->length() + strlen("<length > ") +
|
||||
CountDecimalDigits(str->length()) < bufsize;
|
||||
|
||||
n = JS_snprintf(buf, bufsize, "<length %d%s> ",
|
||||
(int)str->length(),
|
||||
willFit ? "" : " (truncated)");
|
||||
buf += n;
|
||||
bufsize -= n;
|
||||
|
||||
PutEscapedString(buf, bufsize, &str->asLinear(), 0);
|
||||
}
|
||||
else
|
||||
JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno));
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
case JSTRACE_IONCODE:
|
||||
case JSTRACE_SHAPE:
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[bufsize - 1] = '\0';
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize)
|
||||
{
|
||||
if (trc->debugPrinter) {
|
||||
trc->debugPrinter(trc, buffer, bufferSize);
|
||||
return buffer;
|
||||
}
|
||||
if (trc->debugPrintIndex != (size_t) - 1) {
|
||||
JS_snprintf(buffer, bufferSize, "%s[%lu]",
|
||||
(const char *)trc->debugPrintArg,
|
||||
trc->debugPrintIndex);
|
||||
return buffer;
|
||||
}
|
||||
return (const char*)trc->debugPrintArg;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
typedef struct JSHeapDumpNode JSHeapDumpNode;
|
||||
|
183
js/src/jsapi.h
183
js/src/jsapi.h
@ -32,6 +32,8 @@
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
struct JSTracer;
|
||||
|
||||
namespace JS {
|
||||
|
||||
class Latin1CharsZ;
|
||||
@ -1990,187 +1992,6 @@ JSVAL_TRACE_KIND(jsval v)
|
||||
return (JSGCTraceKind) JSVAL_TRACE_KIND_IMPL(JSVAL_TO_IMPL(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tracer callback, called for each traceable thing directly referenced by a
|
||||
* particular object or runtime structure. It is the callback responsibility
|
||||
* to ensure the traversal of the full object graph via calling eventually
|
||||
* JS_TraceChildren on the passed thing. In this case the callback must be
|
||||
* prepared to deal with cycles in the traversal graph.
|
||||
*
|
||||
* kind argument is one of JSTRACE_OBJECT, JSTRACE_STRING or a tag denoting
|
||||
* internal implementation-specific traversal kind. In the latter case the only
|
||||
* operations on thing that the callback can do is to call JS_TraceChildren or
|
||||
* JS_GetTraceThingInfo.
|
||||
*
|
||||
* If eagerlyTraceWeakMaps is true, when we trace a WeakMap visit all
|
||||
* of its mappings. This should be used in cases where the tracer
|
||||
* wants to use the existing liveness of entries.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceCallback)(JSTracer *trc, void **thingp, JSGCTraceKind kind);
|
||||
|
||||
enum WeakMapTraceKind {
|
||||
DoNotTraceWeakMaps = 0,
|
||||
TraceWeakMapValues = 1,
|
||||
TraceWeakMapKeysValues = 2
|
||||
};
|
||||
|
||||
struct JSTracer {
|
||||
JSRuntime *runtime;
|
||||
JSTraceCallback callback;
|
||||
JSTraceNamePrinter debugPrinter;
|
||||
const void *debugPrintArg;
|
||||
size_t debugPrintIndex;
|
||||
WeakMapTraceKind eagerlyTraceWeakMaps;
|
||||
#ifdef JS_GC_ZEAL
|
||||
void *realLocation;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Set debugging information about a reference to a traceable thing to prepare
|
||||
* for the following call to JS_CallTracer.
|
||||
*
|
||||
* When printer is null, arg must be const char * or char * C string naming
|
||||
* the reference and index must be either (size_t)-1 indicating that the name
|
||||
* alone describes the reference or it must be an index into some array vector
|
||||
* that stores the reference.
|
||||
*
|
||||
* When printer callback is not null, the arg and index arguments are
|
||||
* available to the callback as debugPrintArg and debugPrintIndex fields
|
||||
* of JSTracer.
|
||||
*
|
||||
* The storage for name or callback's arguments needs to live only until
|
||||
* the following call to JS_CallTracer returns.
|
||||
*/
|
||||
# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
|
||||
JS_BEGIN_MACRO \
|
||||
(trc)->debugPrinter = (printer); \
|
||||
(trc)->debugPrintArg = (arg); \
|
||||
(trc)->debugPrintIndex = (index); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
* Sets the real location for a marked reference, when passing the address
|
||||
* directly is not feasable.
|
||||
*
|
||||
* FIXME: This is currently overcomplicated by our need to nest calls for Values
|
||||
* stored as keys in hash tables, but will get simplified once we can rekey
|
||||
* in-place.
|
||||
*/
|
||||
#ifdef JS_GC_ZEAL
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!(trc)->realLocation || !(location)) \
|
||||
(trc)->realLocation = (location); \
|
||||
JS_END_MACRO
|
||||
# define JS_UNSET_TRACING_LOCATION(trc) \
|
||||
JS_BEGIN_MACRO \
|
||||
(trc)->realLocation = NULL; \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define JS_SET_TRACING_LOCATION(trc, location) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_END_MACRO
|
||||
# define JS_UNSET_TRACING_LOCATION(trc) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Convenience macro to describe the argument of JS_CallTracer using C string
|
||||
* and index.
|
||||
*/
|
||||
# define JS_SET_TRACING_INDEX(trc, name, index) \
|
||||
JS_SET_TRACING_DETAILS(trc, NULL, name, index)
|
||||
|
||||
/*
|
||||
* Convenience macro to describe the argument of JS_CallTracer using C string.
|
||||
*/
|
||||
# define JS_SET_TRACING_NAME(trc, name) \
|
||||
JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1)
|
||||
|
||||
/*
|
||||
* The JS_Call*Tracer family of functions traces the given GC thing reference.
|
||||
* This performs the tracing action configured on the given JSTracer:
|
||||
* typically calling the JSTracer::callback or marking the thing as live.
|
||||
*
|
||||
* The argument to JS_Call*Tracer is an in-out param: when the function
|
||||
* returns, the garbage collector might have moved the GC thing. In this case,
|
||||
* the reference passed to JS_Call*Tracer will be updated to the object's new
|
||||
* location. Callers of this method are responsible for updating any state
|
||||
* that is dependent on the object's address. For example, if the object's
|
||||
* address is used as a key in a hashtable, then the object must be removed
|
||||
* and re-inserted with the correct hash.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name);
|
||||
|
||||
template <typename HashSetEnum>
|
||||
inline void
|
||||
JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name)
|
||||
{
|
||||
JSObject *updated = key;
|
||||
JS_SET_TRACING_LOCATION(trc, reinterpret_cast<void *>(&const_cast<JSObject *&>(key)));
|
||||
JS_CallObjectTracer(trc, &updated, name);
|
||||
if (updated != key)
|
||||
e.rekeyFront(key, updated);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trace an object that is known to always be tenured. No post barriers are
|
||||
* required in this case.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name);
|
||||
|
||||
/*
|
||||
* API for JSTraceCallback implementations.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceRuntime(JSTracer *trc);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
|
||||
void *thing, JSGCTraceKind kind, bool includeDetails);
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/*
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/Tracer.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
class JSAtom;
|
||||
|
@ -70,6 +70,7 @@ EXPORTS.js += [
|
||||
'../public/RequiredDefines.h',
|
||||
'../public/RootingAPI.h',
|
||||
'../public/StructuredClone.h',
|
||||
'../public/Tracer.h',
|
||||
'../public/TypeDecls.h',
|
||||
'../public/Utility.h',
|
||||
'../public/Value.h',
|
||||
@ -132,6 +133,7 @@ CPP_SOURCES += [
|
||||
'TestingFunctions.cpp',
|
||||
'ThreadPool.cpp',
|
||||
'TokenStream.cpp',
|
||||
'Tracer.cpp',
|
||||
'TypeRepresentation.cpp',
|
||||
'TypedArrayObject.cpp',
|
||||
'Unicode.cpp',
|
||||
|
@ -92,6 +92,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "xpcpublic.h"
|
||||
#include "js/Tracer.h"
|
||||
#include "pldhash.h"
|
||||
#include "nscore.h"
|
||||
#include "nsXPCOM.h"
|
||||
|
Loading…
Reference in New Issue
Block a user