зеркало из https://github.com/mozilla/gecko-dev.git
Bug 612015 - Put all external strings in one arena r=igor
This commit is contained in:
Родитель
8dec940d29
Коммит
3d391d9cee
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче