Bug 612015 - Put all external strings in one arena r=igor

This commit is contained in:
Gregor Wagner 2010-11-15 12:39:00 -08:00
Родитель 8dec940d29
Коммит 3d391d9cee
13 изменённых файлов: 128 добавлений и 178 удалений

Просмотреть файл

@ -95,6 +95,7 @@
#include "jsscopeinlines.h"
#include "jscntxtinlines.h"
#include "jsregexpinlines.h"
#include "jsstrinlines.h"
#include "assembler/wtf/Platform.h"
#if ENABLE_YARR_JIT
@ -2680,25 +2681,26 @@ JS_FlushCaches(JSContext *cx)
JS_PUBLIC_API(intN)
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
{
return js_ChangeExternalStringFinalizer(NULL, finalizer);
return JSExternalString::changeFinalizer(NULL, finalizer);
}
JS_PUBLIC_API(intN)
JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
{
return js_ChangeExternalStringFinalizer(finalizer, NULL);
return JSExternalString::changeFinalizer(finalizer, NULL);
}
JS_PUBLIC_API(JSString *)
JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
{
CHECK_REQUEST(cx);
JS_ASSERT(uintN(type) < JS_EXTERNAL_STRING_LIMIT);
JS_ASSERT(uintN(type) < JSExternalString::TYPE_LIMIT);
JSString *str = js_NewGCExternalString(cx, uintN(type));
JSExternalString *str = js_NewGCExternalString(cx, uintN(type));
if (!str)
return NULL;
str->initFlat(chars, length);
str->externalStringType = type;
cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
return str;
}

Просмотреть файл

@ -117,31 +117,26 @@ JS_STATIC_ASSERT(JSTRACE_XML == 2);
*/
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML);
/*
* Check consistency of external string constants from JSFinalizeGCThingKind.
*/
JS_STATIC_ASSERT(FINALIZE_EXTERNAL_STRING_LAST - FINALIZE_EXTERNAL_STRING0 ==
JS_EXTERNAL_STRING_LIMIT - 1);
/*
* Everything we store in the heap must be a multiple of the cell size.
*/
JS_STATIC_ASSERT(sizeof(JSString) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSShortString) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSFunction) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSString) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSShortString) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSFunction) % sizeof(FreeCell) == 0);
#ifdef JSXML
JS_STATIC_ASSERT(sizeof(JSXML) % sizeof(FreeCell) == 0);
JS_STATIC_ASSERT(sizeof(JSXML) % sizeof(FreeCell) == 0);
#endif
/*
* All arenas must be exactly 4k.
*/
JS_STATIC_ASSERT(sizeof(Arena<JSString>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSShortString>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSObject>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSFunction>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSXML>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSString>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSExternalString>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSShortString>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSObject>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSFunction>) == 4096);
JS_STATIC_ASSERT(sizeof(Arena<JSXML>) == 4096);
#ifdef JS_GCMETER
# define METER(x) ((void) (x))
@ -248,13 +243,12 @@ checkArenaListsForThing(JSCompartment *comp, void *thing) {
#if JS_HAS_XML_SUPPORT
comp->arenas[FINALIZE_XML].arenasContainThing<JSXML>(thing) ||
#endif
comp->arenas[FINALIZE_STRING].arenasContainThing<JSString>(thing) ||
comp->arenas[FINALIZE_EXTERNAL_STRING].arenasContainThing<JSExternalString>(thing) ||
comp->arenas[FINALIZE_SHORT_STRING].arenasContainThing<JSShortString>(thing)) {
return true;
}
for (unsigned i = FINALIZE_STRING; i <= FINALIZE_EXTERNAL_STRING_LAST; i++) {
if (comp->arenas[i].arenasContainThing<JSString>(thing))
return true;
}
return false;
}
#endif
@ -633,16 +627,11 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w, uint32 &traceKind)
test = MarkCell<JSObject_Slots16>(cell, trc);
break;
case FINALIZE_STRING:
case FINALIZE_EXTERNAL_STRING0:
case FINALIZE_EXTERNAL_STRING1:
case FINALIZE_EXTERNAL_STRING2:
case FINALIZE_EXTERNAL_STRING3:
case FINALIZE_EXTERNAL_STRING4:
case FINALIZE_EXTERNAL_STRING5:
case FINALIZE_EXTERNAL_STRING6:
case FINALIZE_EXTERNAL_STRING7:
test = MarkCell<JSString>(cell, trc);
break;
case FINALIZE_EXTERNAL_STRING:
test = MarkCell<JSExternalString>(cell, trc);
break;
case FINALIZE_SHORT_STRING:
test = MarkCell<JSShortString>(cell, trc);
break;
@ -1139,15 +1128,9 @@ RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
case FINALIZE_OBJECT16:
return RefillTypedFreeList<JSObject_Slots16>(cx, thingKind);
case FINALIZE_STRING:
case FINALIZE_EXTERNAL_STRING0:
case FINALIZE_EXTERNAL_STRING1:
case FINALIZE_EXTERNAL_STRING2:
case FINALIZE_EXTERNAL_STRING3:
case FINALIZE_EXTERNAL_STRING4:
case FINALIZE_EXTERNAL_STRING5:
case FINALIZE_EXTERNAL_STRING6:
case FINALIZE_EXTERNAL_STRING7:
return RefillTypedFreeList<JSString>(cx, thingKind);
case FINALIZE_EXTERNAL_STRING:
return RefillTypedFreeList<JSExternalString>(cx, thingKind);
case FINALIZE_SHORT_STRING:
return RefillTypedFreeList<JSShortString>(cx, thingKind);
case FINALIZE_FUNCTION:
@ -1164,7 +1147,7 @@ RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
intN
js_GetExternalStringGCType(JSString *str) {
return GetExternalStringGCType(str);
return GetExternalStringGCType((JSExternalString *)str);
}
uint32
@ -1355,16 +1338,11 @@ GCMarker::markDelayedChildren()
reinterpret_cast<Arena<JSObject_Slots16> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_STRING:
case FINALIZE_EXTERNAL_STRING0:
case FINALIZE_EXTERNAL_STRING1:
case FINALIZE_EXTERNAL_STRING2:
case FINALIZE_EXTERNAL_STRING3:
case FINALIZE_EXTERNAL_STRING4:
case FINALIZE_EXTERNAL_STRING5:
case FINALIZE_EXTERNAL_STRING6:
case FINALIZE_EXTERNAL_STRING7:
reinterpret_cast<Arena<JSString> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_EXTERNAL_STRING:
reinterpret_cast<Arena<JSExternalString> *>(a)->markDelayedChildren(this);
break;
case FINALIZE_SHORT_STRING:
JS_ASSERT(false);
break;
@ -1766,19 +1744,6 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data)
}
}
intN
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop)
{
for (uintN i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
if (str_finalizers[i] == oldop) {
str_finalizers[i] = newop;
return intN(i);
}
}
return -1;
}
/*
* This function is called from js_FinishAtomState to force the finalization
* of the permanently interned strings when cx is not available.
@ -1805,17 +1770,8 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str)
return;
if (thingKind == FINALIZE_STRING) {
rt->free(chars);
} else if (thingKind != FINALIZE_SHORT_STRING) {
unsigned type = thingKind - FINALIZE_EXTERNAL_STRING0;
JS_ASSERT(type < JS_ARRAY_LENGTH(str_finalizers));
JSStringFinalizeOp finalizer = str_finalizers[type];
if (finalizer) {
/*
* Assume that the finalizer for the permanently interned
* string knows how to deal with null context.
*/
finalizer(NULL, str);
}
} else if (thingKind == FINALIZE_EXTERNAL_STRING) {
((JSExternalString *)str)->finalize();
}
}
}
@ -1875,7 +1831,7 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
METER(nthings++);
continue;
} else {
thing->finalize(cx, thingKind);
thing->finalize(cx);
#ifdef DEBUG
memset(thing, JS_FREE_PATTERN, sizeof(T));
#endif
@ -2254,8 +2210,7 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
for (JSCompartment **comp = rt->compartments.begin(); comp != rt->compartments.end(); comp++) {
FinalizeArenaList<JSShortString>(*comp, cx, FINALIZE_SHORT_STRING);
FinalizeArenaList<JSString>(*comp, cx, FINALIZE_STRING);
for (unsigned i = FINALIZE_EXTERNAL_STRING0; i <= FINALIZE_EXTERNAL_STRING_LAST; ++i)
FinalizeArenaList<JSString>(*comp, cx, i);
FinalizeArenaList<JSExternalString>(*comp, cx, FINALIZE_EXTERNAL_STRING);
}
TIMESTAMP(sweepStringEnd);

Просмотреть файл

@ -90,20 +90,11 @@ enum FinalizeKind {
#endif
FINALIZE_SHORT_STRING,
FINALIZE_STRING,
FINALIZE_EXTERNAL_STRING0,
FINALIZE_EXTERNAL_STRING1,
FINALIZE_EXTERNAL_STRING2,
FINALIZE_EXTERNAL_STRING3,
FINALIZE_EXTERNAL_STRING4,
FINALIZE_EXTERNAL_STRING5,
FINALIZE_EXTERNAL_STRING6,
FINALIZE_EXTERNAL_STRING7,
FINALIZE_EXTERNAL_STRING_LAST = FINALIZE_EXTERNAL_STRING7,
FINALIZE_EXTERNAL_STRING,
FINALIZE_LIMIT
};
const uintN JS_FINALIZE_OBJECT_LIMIT = 6;
const uintN JS_EXTERNAL_STRING_LIMIT = 8;
/* Every arena has a header. */
struct ArenaHeader {
@ -270,8 +261,6 @@ template <typename T>
inline Arena<T> *
EmptyArenaLists::getTypedFreeList(unsigned thingKind) {
JS_ASSERT(thingKind < FINALIZE_LIMIT);
if (thingKind >= FINALIZE_EXTERNAL_STRING0)
thingKind = FINALIZE_STRING;
Arena<T> *arena = (Arena<T>*) freeLists[thingKind];
if (arena) {
freeLists[thingKind] = freeLists[thingKind]->header()->next;
@ -303,8 +292,6 @@ inline void
EmptyArenaLists::insert(Arena<T> *arena) {
unsigned thingKind = arena->header()->thingKind;
JS_ASSERT(thingKind < FINALIZE_LIMIT);
if (thingKind >= FINALIZE_EXTERNAL_STRING0)
thingKind = FINALIZE_STRING;
arena->header()->next = freeLists[thingKind];
freeLists[thingKind] = (Arena<FreeCell> *) arena;
}
@ -490,7 +477,7 @@ const float GC_HEAP_GROWTH_FACTOR = 3.0f;
static inline size_t
GetFinalizableTraceKind(size_t thingKind)
{
JS_STATIC_ASSERT(JS_EXTERNAL_STRING_LIMIT == 8);
JS_STATIC_ASSERT(JSExternalString::TYPE_LIMIT == 8);
static const uint8 map[FINALIZE_LIMIT] = {
JSTRACE_OBJECT, /* FINALIZE_OBJECT0 */
@ -505,14 +492,7 @@ GetFinalizableTraceKind(size_t thingKind)
#endif
JSTRACE_STRING, /* FINALIZE_SHORT_STRING */
JSTRACE_STRING, /* FINALIZE_STRING */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING0 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING1 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING2 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING3 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING4 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING5 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING6 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING7 */
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING */
};
JS_ASSERT(thingKind < FINALIZE_LIMIT);
@ -523,7 +503,7 @@ static inline bool
IsFinalizableStringKind(unsigned thingKind)
{
return unsigned(FINALIZE_SHORT_STRING) <= thingKind &&
thingKind <= unsigned(FINALIZE_EXTERNAL_STRING_LAST);
thingKind <= unsigned(FINALIZE_EXTERNAL_STRING);
}
/*
@ -531,14 +511,14 @@ IsFinalizableStringKind(unsigned thingKind)
* with JS_NewExternalString.
*/
static inline intN
GetExternalStringGCType(JSString *str)
GetExternalStringGCType(JSExternalString *str)
{
JS_STATIC_ASSERT(FINALIZE_STRING + 1 == FINALIZE_EXTERNAL_STRING0);
JS_STATIC_ASSERT(FINALIZE_STRING + 1 == FINALIZE_EXTERNAL_STRING);
JS_ASSERT(!JSString::isStatic(str));
unsigned thingKind = GetArena<JSString>((Cell *)str)->header()->thingKind;
unsigned thingKind = str->externalStringType;
JS_ASSERT(IsFinalizableStringKind(thingKind));
return intN(thingKind) - intN(FINALIZE_EXTERNAL_STRING0);
return intN(thingKind);
}
static inline uint32
@ -751,10 +731,6 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes);
extern void
js_FinishGC(JSRuntime *rt);
extern intN
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop);
extern JSBool
js_AddRoot(JSContext *cx, js::Value *vp, const char *name);

Просмотреть файл

@ -154,12 +154,12 @@ js_NewGCShortString(JSContext *cx)
return NewFinalizableGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING);
}
inline JSString *
inline JSExternalString *
js_NewGCExternalString(JSContext *cx, uintN type)
{
JS_ASSERT(type < js::gc::JS_EXTERNAL_STRING_LIMIT);
type += js::gc::FINALIZE_EXTERNAL_STRING0;
return NewFinalizableGCThing<JSString>(cx, type);
JS_ASSERT(type < JSExternalString::TYPE_LIMIT);
JSExternalString *str = NewFinalizableGCThing<JSExternalString>(cx, js::gc::FINALIZE_EXTERNAL_STRING);
return str;
}
inline JSFunction*
@ -437,9 +437,7 @@ MarkKind(JSTracer *trc, void *thing, uint32 kind)
Mark(trc, reinterpret_cast<JSObject *>(thing));
break;
case JSTRACE_STRING:
if (JSString::isStatic((JSString *)thing))
return;
Mark(trc, reinterpret_cast<JSString *>(thing));
MarkString(trc, reinterpret_cast<JSString *>(thing));
break;
#if JS_HAS_XML_SUPPORT
case JSTRACE_XML:

Просмотреть файл

@ -123,14 +123,7 @@ static const char *const GC_ARENA_NAMES[] = {
#endif
"short string",
"string",
"external_string_0",
"external_string_1",
"external_string_2",
"external_string_3",
"external_string_4",
"external_string_5",
"external_string_6",
"external_string_7",
"external_string",
};
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT);
@ -163,15 +156,8 @@ void GetSizeAndThingsPerArena(int thingKind, size_t &thingSize, size_t &thingsPe
case FINALIZE_OBJECT16:
GetSizeAndThings<JSObject_Slots16>(thingSize, thingsPerArena);
break;
case FINALIZE_EXTERNAL_STRING:
case FINALIZE_STRING:
case FINALIZE_EXTERNAL_STRING0:
case FINALIZE_EXTERNAL_STRING1:
case FINALIZE_EXTERNAL_STRING2:
case FINALIZE_EXTERNAL_STRING3:
case FINALIZE_EXTERNAL_STRING4:
case FINALIZE_EXTERNAL_STRING5:
case FINALIZE_EXTERNAL_STRING6:
case FINALIZE_EXTERNAL_STRING7:
GetSizeAndThings<JSString>(thingSize, thingsPerArena);
break;
case FINALIZE_SHORT_STRING:

Просмотреть файл

@ -990,7 +990,7 @@ struct JSObject : js::gc::Cell {
void *priv, bool useHoles);
inline void finish(JSContext *cx);
JS_ALWAYS_INLINE void finalize(JSContext *cx, unsigned thindKind);
JS_ALWAYS_INLINE void finalize(JSContext *cx);
/*
* Like init, but also initializes map. The catch: proto must be the result

Просмотреть файл

@ -118,11 +118,8 @@ JSObject::syncSpecialEquality()
}
inline void
JSObject::finalize(JSContext *cx, unsigned thingKind)
JSObject::finalize(JSContext *cx)
{
JS_ASSERT(thingKind >= js::gc::FINALIZE_OBJECT0 &&
thingKind <= js::gc::FINALIZE_FUNCTION);
/* Cope with stillborn objects that have no map. */
if (!map)
return;

Просмотреть файл

@ -55,6 +55,7 @@
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jspropertytree.h"
#include "jsstrinlines.h"
#ifdef _MSC_VER
#pragma warning(push)

Просмотреть файл

@ -89,11 +89,6 @@ using namespace js::gc;
JS_STATIC_ASSERT(size_t(JSString::MAX_LENGTH) <= size_t(JSVAL_INT_MAX));
JS_STATIC_ASSERT(JSString::MAX_LENGTH <= JSVAL_INT_MAX);
JS_STATIC_ASSERT(JS_EXTERNAL_STRING_LIMIT == 8);
JSStringFinalizeOp str_finalizers[JS_EXTERNAL_STRING_LIMIT] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
const jschar *
js_GetStringChars(JSContext *cx, JSString *str)
{
@ -189,6 +184,11 @@ JSString::flatten()
}
}
JS_STATIC_ASSERT(JSExternalString::TYPE_LIMIT == 8);
JSStringFinalizeOp JSExternalString::str_finalizers[JSExternalString::TYPE_LIMIT] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
#ifdef JS_TRACER
int32 JS_FASTCALL

Просмотреть файл

@ -68,8 +68,6 @@ enum {
NUM_HUNDRED_STRINGS = 156U
};
extern JSStringFinalizeOp str_finalizers[8];
extern jschar *
js_GetDependentStringChars(JSString *str);
@ -160,6 +158,7 @@ struct JSString {
JSString *mRight; /* in rope interior and top nodes */
};
} e;
uintN externalStringType; /* for external strings. */
};
/*
@ -527,9 +526,30 @@ struct JSString {
static JSString *lookupStaticString(const jschar *chars, size_t length);
JS_ALWAYS_INLINE void finalize(JSContext *cx, unsigned thingKind);
JS_ALWAYS_INLINE void finalize(JSContext *cx);
};
struct JSExternalString : JSString {
static const uintN TYPE_LIMIT = 8;
static JSStringFinalizeOp str_finalizers[TYPE_LIMIT];
static intN changeFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop) {
for (uintN i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
if (str_finalizers[i] == oldop) {
str_finalizers[i] = newop;
return intN(i);
}
}
return -1;
}
void finalize(JSContext *cx);
void finalize();
};
JS_STATIC_ASSERT(sizeof(JSString) == sizeof(JSExternalString));
/*
* Short strings should be created in cases where it's worthwhile to avoid
* mallocing the string buffer for a small string. We keep 2 string headers'
@ -574,7 +594,7 @@ struct JSShortString : js::gc::Cell {
return length <= MAX_SHORT_STRING_LENGTH;
}
JS_ALWAYS_INLINE void finalize(JSContext *cx, unsigned thingKind);
JS_ALWAYS_INLINE void finalize(JSContext *cx);
};
/*

Просмотреть файл

@ -121,48 +121,62 @@ JSString::lookupStaticString(const jschar *chars, size_t length)
}
inline void
JSString::finalize(JSContext *cx, unsigned thingKind) {
if (JS_LIKELY(thingKind == js::gc::FINALIZE_STRING)) {
JS_ASSERT(!JSString::isStatic(this));
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
if (isDependent()) {
JS_ASSERT(dependentBase());
JS_RUNTIME_UNMETER(cx->runtime, liveDependentStrings);
} else if (isFlat()) {
/*
* flatChars for stillborn string is null, but cx->free checks
* for a null pointer on its own.
*/
cx->free(flatChars());
} else if (isTopNode()) {
cx->free(topNodeBuffer());
}
} else {
unsigned type = thingKind - js::gc::FINALIZE_EXTERNAL_STRING0;
JS_ASSERT(type < JS_ARRAY_LENGTH(str_finalizers));
JS_ASSERT(!isStatic(this));
JS_ASSERT(isFlat());
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
/* A stillborn string has null chars. */
jschar *chars = flatChars();
if (!chars)
return;
JSStringFinalizeOp finalizer = str_finalizers[type];
if (finalizer)
finalizer(cx, this);
JSString::finalize(JSContext *cx) {
JS_ASSERT(!JSString::isStatic(this));
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
if (isDependent()) {
JS_ASSERT(dependentBase());
JS_RUNTIME_UNMETER(cx->runtime, liveDependentStrings);
} else if (isFlat()) {
/*
* flatChars for stillborn string is null, but cx->free checks
* for a null pointer on its own.
*/
cx->free(flatChars());
} else if (isTopNode()) {
cx->free(topNodeBuffer());
}
}
inline void
JSShortString::finalize(JSContext *cx, unsigned thingKind)
JSShortString::finalize(JSContext *cx)
{
JS_ASSERT(js::gc::FINALIZE_SHORT_STRING == thingKind);
JS_ASSERT(!JSString::isStatic(header()));
JS_ASSERT(header()->isFlat());
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
}
inline void
JSExternalString::finalize(JSContext *cx)
{
JS_ASSERT(unsigned(externalStringType) < JS_ARRAY_LENGTH(str_finalizers));
JS_ASSERT(!isStatic(this));
JS_ASSERT(isFlat());
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
/* A stillborn string has null chars. */
jschar *chars = flatChars();
if (!chars)
return;
JSStringFinalizeOp finalizer = str_finalizers[externalStringType];
if (finalizer)
finalizer(cx, this);
}
inline void
JSExternalString::finalize()
{
JS_ASSERT(unsigned(externalStringType) < JS_ARRAY_LENGTH(str_finalizers));
JSStringFinalizeOp finalizer = str_finalizers[externalStringType];
if (finalizer) {
/*
* Assume that the finalizer for the permanently interned
* string knows how to deal with null context.
*/
finalizer(NULL, this);
}
}
inline
JSRopeBuilder::JSRopeBuilder(JSContext *cx)
: cx(cx), mStr(cx->runtime->emptyString) {}

Просмотреть файл

@ -74,6 +74,7 @@
#include "jscntxtinlines.h"
#include "jsinterpinlines.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
#ifdef DEBUG
#include <string.h> /* for #ifdef DEBUG memset calls */

Просмотреть файл

@ -190,7 +190,7 @@ struct JSXML : js::gc::Cell {
JSString *value;
} u;
void finalize(JSContext *cx, unsigned thingKind) {
void finalize(JSContext *cx) {
if (JSXML_HAS_KIDS(this)) {
xml_kids.finish(cx);
if (xml_class == JSXML_CLASS_ELEMENT) {