зеркало из https://github.com/mozilla/pjs.git
Back out last change.
This commit is contained in:
Родитель
3c600d1928
Коммит
757c358c6b
|
@ -59,34 +59,6 @@
|
|||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
|
||||
* given pc in a script.
|
||||
*/
|
||||
typedef struct JSGSNCache {
|
||||
JSScript *script;
|
||||
JSDHashTable table;
|
||||
#ifdef JS_GSNMETER
|
||||
uint32 hits;
|
||||
uint32 misses;
|
||||
uint32 fills;
|
||||
uint32 clears;
|
||||
# define GSN_CACHE_METER(cx,cnt) (++JS_GSN_CACHE(cx).cnt)
|
||||
#else
|
||||
# define GSN_CACHE_METER(cx,cnt) /* nothing */
|
||||
#endif
|
||||
} JSGSNCache;
|
||||
|
||||
#define JS_CLEAR_GSN_CACHE(cx) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_GSN_CACHE(cx).script = NULL; \
|
||||
if (JS_GSN_CACHE(cx).table.ops) { \
|
||||
JS_DHashTableFinish(&JS_GSN_CACHE(cx).table); \
|
||||
JS_GSN_CACHE(cx).table.ops = NULL; \
|
||||
} \
|
||||
GSN_CACHE_METER(cx, clears); \
|
||||
JS_END_MACRO
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/*
|
||||
|
@ -113,19 +85,8 @@ struct JSThread {
|
|||
/* Flag indicating that the current thread is executing close hooks. */
|
||||
JSBool gcRunningCloseHooks;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Store the GSN cache in struct JSThread, not struct JSContext, both to
|
||||
* save space and to simplify cleanup in js_GC. Any embedding (Firefox
|
||||
* or another Gecko application) that uses many contexts per thread is
|
||||
* unlikely to interleave js_GetSrcNote-intensive loops in the decompiler
|
||||
* among two or more contexts running script in one thread.
|
||||
*/
|
||||
JSGSNCache gsnCache;
|
||||
};
|
||||
|
||||
#define JS_GSN_CACHE(cx) ((cx)->thread->gsnCache)
|
||||
|
||||
extern void JS_DLL_CALLBACK
|
||||
js_ThreadDestructorCB(void *ptr);
|
||||
|
||||
|
@ -389,18 +350,6 @@ struct JSRuntime {
|
|||
*/
|
||||
JSNativeIteratorState *nativeIteratorStates;
|
||||
|
||||
#ifndef JS_THREADSAFE
|
||||
/*
|
||||
* For thread-unsafe embeddings, the GSN cache lives in the runtime and
|
||||
* not each context, since we expect it to be filled once when decompiling
|
||||
* a longer script, then hit repeatedly as js_GetSrcNote is called during
|
||||
* the decompiler activation that filled it.
|
||||
*/
|
||||
JSGSNCache gsnCache;
|
||||
|
||||
#define JS_GSN_CACHE(cx) ((cx)->runtime->gsnCache)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Function invocation metering. */
|
||||
jsrefcount inlineCalls;
|
||||
|
@ -766,11 +715,37 @@ struct JSContext {
|
|||
/* Top of the GC mark stack. */
|
||||
void *gcCurrentMarkNode;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for
|
||||
* a given pc in a script.
|
||||
*/
|
||||
struct JSGSNCache {
|
||||
JSScript *script;
|
||||
JSDHashTable table;
|
||||
#ifdef JS_GSNMETER
|
||||
uint32 hits;
|
||||
uint32 misses;
|
||||
uint32 fills;
|
||||
uint32 clears;
|
||||
# define GSN_CACHE_METER(cx,cnt) (++(cx)->gsnCache.cnt)
|
||||
#else
|
||||
# define GSN_CACHE_METER(cx,cnt) /* nothing */
|
||||
#endif
|
||||
} gsnCache;
|
||||
};
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
# define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
|
||||
#endif
|
||||
#define JS_CLEAR_GSN_CACHE(cx) \
|
||||
JS_BEGIN_MACRO \
|
||||
(cx)->gsnCache.script = NULL; \
|
||||
if ((cx)->gsnCache.table.ops) { \
|
||||
JS_DHashTableFinish(&(cx)->gsnCache.table); \
|
||||
(cx)->gsnCache.table.ops = NULL; \
|
||||
} \
|
||||
GSN_CACHE_METER(cx, clears); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* FIXME(bug 332648): Move this into a public header. */
|
||||
|
|
|
@ -2824,11 +2824,8 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
|
|||
* freelist more than once. To avoid redundant clearing we unroll the
|
||||
* current thread's step.
|
||||
*
|
||||
* Also, in case a JSScript wrapped within an object was finalized, we
|
||||
* null acx->thread->gsnCache.script and finish the cache's hashtable.
|
||||
* Note that js_DestroyScript, called from script_finalize, will have
|
||||
* already cleared cx->thread->gsnCache above during finalization, so we
|
||||
* don't have to here.
|
||||
* Also, in case a JSScript wrapped in an object was finalized, we clear
|
||||
* the acx->gsnCache.script pointer and finish the cache's hashtable.
|
||||
*/
|
||||
memset(cx->thread->gcFreeLists, 0, sizeof cx->thread->gcFreeLists);
|
||||
iter = NULL;
|
||||
|
@ -2838,9 +2835,6 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
|
|||
memset(acx->thread->gcFreeLists, 0, sizeof acx->thread->gcFreeLists);
|
||||
JS_CLEAR_GSN_CACHE(acx);
|
||||
}
|
||||
#else
|
||||
/* The thread-unsafe case just has to clear the runtime's GSN cache. */
|
||||
JS_CLEAR_GSN_CACHE(cx);
|
||||
#endif
|
||||
|
||||
restart:
|
||||
|
@ -2977,7 +2971,10 @@ restart:
|
|||
* Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
|
||||
* so that any attempt to allocate a GC-thing from a finalizer will fail,
|
||||
* rather than nest badly and leave the unmarked newborn to be swept.
|
||||
*
|
||||
*/
|
||||
js_SweepAtomState(&rt->atomState);
|
||||
|
||||
/*
|
||||
* Finalize smaller objects before larger, to guarantee finalization of
|
||||
* GC-allocated obj->slots after obj. See FreeSlots in jsobj.c.
|
||||
*/
|
||||
|
@ -3024,16 +3021,14 @@ restart:
|
|||
|
||||
/*
|
||||
* Sweep the runtime's property tree after finalizing objects, in case any
|
||||
* had watchpoints referencing tree nodes. Then sweep atoms, which may be
|
||||
* referenced from dead property ids.
|
||||
* had watchpoints referencing tree nodes.
|
||||
*/
|
||||
js_SweepScopeProperties(rt);
|
||||
js_SweepAtomState(&rt->atomState);
|
||||
|
||||
/*
|
||||
* Sweep script filenames after sweeping functions in the generic loop
|
||||
* above. In this way when a scripted function's finalizer destroys the
|
||||
* script and calls rt->destroyScriptHook, the hook can still access the
|
||||
* above. In this way when scripted function's finalizer destroys script
|
||||
* triggering a call to rt->destroyScriptHook, the hook can still access
|
||||
* script's filename. See bug 323267.
|
||||
*/
|
||||
js_SweepScriptFilenames(rt);
|
||||
|
|
|
@ -1399,7 +1399,7 @@ js_DestroyScript(JSContext *cx, JSScript *script)
|
|||
js_FreeAtomMap(cx, &script->atomMap);
|
||||
if (script->principals)
|
||||
JSPRINCIPALS_DROP(cx, script->principals);
|
||||
if (JS_GSN_CACHE(cx).script == script)
|
||||
if (cx->gsnCache.script == script)
|
||||
JS_CLEAR_GSN_CACHE(cx);
|
||||
JS_free(cx, script);
|
||||
}
|
||||
|
@ -1442,11 +1442,10 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||
if ((uint32)target >= script->length)
|
||||
return NULL;
|
||||
|
||||
if (JS_GSN_CACHE(cx).script == script) {
|
||||
if (cx->gsnCache.script == script) {
|
||||
GSN_CACHE_METER(cx, hits);
|
||||
entry = (GSNCacheEntry *)
|
||||
JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
|
||||
JS_DHASH_LOOKUP);
|
||||
JS_DHashTableOperate(&cx->gsnCache.table, pc, JS_DHASH_LOOKUP);
|
||||
return entry->sn;
|
||||
}
|
||||
|
||||
|
@ -1464,7 +1463,7 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||
}
|
||||
}
|
||||
|
||||
if (JS_GSN_CACHE(cx).script != script &&
|
||||
if (cx->gsnCache.script != script &&
|
||||
script->length >= GSN_CACHE_THRESHOLD) {
|
||||
JS_CLEAR_GSN_CACHE(cx);
|
||||
nsrcnotes = 0;
|
||||
|
@ -1473,9 +1472,9 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||
if (SN_IS_GETTABLE(sn))
|
||||
++nsrcnotes;
|
||||
}
|
||||
if (!JS_DHashTableInit(&JS_GSN_CACHE(cx).table, JS_DHashGetStubOps(),
|
||||
NULL, sizeof(GSNCacheEntry), nsrcnotes)) {
|
||||
JS_GSN_CACHE(cx).table.ops = NULL;
|
||||
if (!JS_DHashTableInit(&cx->gsnCache.table, JS_DHashGetStubOps(), NULL,
|
||||
sizeof(GSNCacheEntry), nsrcnotes)) {
|
||||
cx->gsnCache.table.ops = NULL;
|
||||
} else {
|
||||
pc = script->code;
|
||||
for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
|
||||
|
@ -1483,13 +1482,13 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||
pc += SN_DELTA(sn);
|
||||
if (SN_IS_GETTABLE(sn)) {
|
||||
entry = (GSNCacheEntry *)
|
||||
JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
|
||||
JS_DHashTableOperate(&cx->gsnCache.table, pc,
|
||||
JS_DHASH_ADD);
|
||||
entry->pc = pc;
|
||||
entry->sn = sn;
|
||||
}
|
||||
}
|
||||
JS_GSN_CACHE(cx).script = script;
|
||||
cx->gsnCache.script = script;
|
||||
GSN_CACHE_METER(cx, fills);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче