Bug 511237 - Remove primary use of Fragmento from jsregexp, r=dmandelin.

This commit is contained in:
Graydon Hoare 2009-08-18 15:32:54 -07:00
parent 571bd08a08
commit ebe9c3f20b
6 changed files with 70 additions and 51 deletions

View File

@ -100,6 +100,7 @@ namespace nanojit {
class Fragment;
class Fragmento;
class LirBuffer;
extern "C++" { template<typename K, typename V, typename H> class HashMap; }
}
class TraceRecorder;
class VMAllocator;
@ -114,6 +115,12 @@ typedef Queue<uint16> SlotList;
#define FRAGMENT_TABLE_SIZE 512
struct VMFragment;
#ifdef __cplusplus
struct REHashKey;
struct REHashFn;
typedef nanojit::HashMap<REHashKey, nanojit::Fragment*, REHashFn> REHashMap;
#endif
#define MONITOR_N_GLOBAL_STATES 4
struct GlobalState {
JSObject* globalObj;
@ -181,6 +188,7 @@ struct JSTraceMonitor {
CLS(nanojit::Assembler) reAssembler;
CLS(nanojit::LirBuffer) reLirBuf;
CLS(nanojit::Fragmento) reFragmento;
CLS(REHashMap) reFragments;
/* Keep a list of recorders we need to abort on cache flush. */
CLS(TraceRecorder) abortStack;

View File

@ -2006,41 +2006,32 @@ typedef JSTempVector<LIns *> LInsList;
/* Dummy GC for nanojit placement new. */
static GC gc;
static void *
HashRegExp(uint16 flags, const jschar *s, size_t n)
{
uint32 h;
for (h = 0; n; s++, n--)
h = JS_ROTATE_LEFT32(h, 4) ^ *s;
return (void *)(h + flags);
}
struct RESideExit : public SideExit {
size_t re_length;
uint16 re_flags;
jschar re_chars[1];
};
/* Return the cached fragment for the given regexp, or NULL. */
/* Return the cached fragment for the given regexp, or create one. */
static Fragment*
LookupNativeRegExp(JSContext* cx, void* hash, uint16 re_flags,
LookupNativeRegExp(JSContext* cx, uint16 re_flags,
const jschar* re_chars, size_t re_length)
{
Fragmento* fragmento = JS_TRACE_MONITOR(cx).reFragmento;
Fragment* fragment = fragmento->getLoop(hash);
while (fragment) {
if (fragment->lastIns) {
RESideExit *exit = (RESideExit*)fragment->lastIns->record()->exit;
if (exit->re_flags == re_flags &&
exit->re_length == re_length &&
!memcmp(exit->re_chars, re_chars, re_length * sizeof(jschar))) {
return fragment;
}
}
fragment = fragment->peer;
JSTraceMonitor *tm = &JS_TRACE_MONITOR(cx);
VMAllocator &alloc = *tm->reAllocator;
REHashMap &table = *tm->reFragments;
REHashKey k(re_length, re_flags, re_chars);
Fragment *frag = table.get(k);
if (!frag) {
frag = new (alloc) Fragment(0);
frag->lirbuf = tm->reLirBuf;
frag->root = frag;
/*
* Copy the re_chars portion of the hash key into the Allocator, so
* its lifecycle is disconnected from the lifecycle of the
* underlying regexp.
*/
k.re_chars = (const jschar*) new (alloc) jschar[re_length];
memcpy((void*) k.re_chars, re_chars, re_length * sizeof(jschar));
table.put(k, frag);
}
return NULL;
return frag;
}
static JSBool
@ -3065,16 +3056,13 @@ class RegExpNativeCompiler {
GuardRecord* insertGuard(const jschar* re_chars, size_t re_length)
{
LIns* skip = lirBufWriter->insSkip(sizeof(GuardRecord) +
sizeof(RESideExit) +
sizeof(SideExit) +
(re_length-1) * sizeof(jschar));
GuardRecord* guard = (GuardRecord *) skip->payload();
memset(guard, 0, sizeof(*guard));
RESideExit* exit = (RESideExit*)(guard+1);
SideExit* exit = (SideExit*)(guard+1);
guard->exit = exit;
guard->exit->target = fragment;
exit->re_flags = re->flags;
exit->re_length = re_length;
memcpy(exit->re_chars, re_chars, re_length * sizeof(jschar));
fragment->lastIns = lir->insGuard(LIR_loop, NULL, skip);
return guard;
}
@ -3163,9 +3151,9 @@ class RegExpNativeCompiler {
fail:
if (alloc.outOfMemory() || oom ||
js_OverfullFragmento(tm, fragmento)) {
fragmento->clearFrags();
tm->reCodeAlloc->sweep();
alloc.reset();
tm->reFragments = new (alloc) REHashMap(alloc);
#ifdef DEBUG
fragmento->labels = new (alloc) LabelMap(alloc, &js_LogController);
lirbuf->names = new (alloc) LirNameMap(alloc, fragmento->labels);
@ -3216,19 +3204,11 @@ typedef void *(FASTCALL *NativeRegExp)(REGlobalData*, const jschar *);
static NativeRegExp
GetNativeRegExp(JSContext* cx, JSRegExp* re)
{
Fragment *fragment;
const jschar *re_chars;
size_t re_length;
Fragmento* fragmento = JS_TRACE_MONITOR(cx).reFragmento;
re->source->getCharsAndLength(re_chars, re_length);
void* hash = HashRegExp(re->flags, re_chars, re_length);
fragment = LookupNativeRegExp(cx, hash, re->flags, re_chars, re_length);
if (!fragment) {
fragment = fragmento->getAnchor(hash);
fragment->lirbuf = JS_TRACE_MONITOR(cx).reLirBuf;
fragment->root = fragment;
}
Fragment *fragment = LookupNativeRegExp(cx, re->flags, re_chars, re_length);
JS_ASSERT(fragment);
if (!fragment->code()) {
if (!CompileRegExpToNative(cx, re, fragment))
return NULL;

View File

@ -865,7 +865,7 @@ getLoop(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalSh
static Fragment*
getAnchor(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32 globalShape, uint32 argc)
{
VMFragment *f = new (&gc) VMFragment(ip, globalObj, globalShape, argc);
VMFragment *f = new VMFragment(ip, globalObj, globalShape, argc);
JS_ASSERT(f);
Fragment *p = getVMFragment(tm, ip, globalObj, globalShape, argc);
@ -6587,6 +6587,7 @@ js_InitJIT(JSTraceMonitor *tm)
&js_LogController);
if (!tm->reFragmento) {
tm->reFragments = new (reAlloc) REHashMap(reAlloc);
Fragmento* fragmento = new (&gc) Fragmento(core, &js_LogController, 32, tm->reCodeAlloc);
verbose_only(fragmento->labels = new (reAlloc) LabelMap(reAlloc, &js_LogController);)
tm->reFragmento = fragmento;

View File

@ -411,7 +411,7 @@ struct VMSideExit : public nanojit::SideExit
}
};
struct VMAllocator : public nanojit::Allocator
class VMAllocator : public nanojit::Allocator
{
public:
@ -438,6 +438,36 @@ public:
uintptr_t mReserve[0x10000];
};
struct REHashKey {
size_t re_length;
uint16 re_flags;
const jschar* re_chars;
REHashKey(size_t re_length, uint16 re_flags, const jschar *re_chars)
: re_length(re_length)
, re_flags(re_flags)
, re_chars(re_chars)
{}
bool operator==(const REHashKey& other) const
{
return ((this->re_length == other.re_length) &&
(this->re_flags == other.re_flags) &&
!memcmp(this->re_chars, other.re_chars,
this->re_length * sizeof(jschar)));
}
};
struct REHashFn {
static size_t hash(const REHashKey& k) {
return
k.re_length +
k.re_flags +
nanojit::murmurhash(k.re_chars, k.re_length * sizeof(jschar));
}
};
struct FrameInfo {
JSObject* callee; // callee function object
JSObject* block; // caller block chain head

View File

@ -250,7 +250,7 @@ namespace nanojit
Fragment *Fragmento::newFrag(const void* ip)
{
GC *gc = _core->gc;
Fragment *f = NJ_NEW(gc, Fragment)(ip);
Fragment *f = new Fragment(ip);
f->blacklistLevel = 5;
return f;
}

View File

@ -128,7 +128,7 @@ namespace nanojit
* It may turn out that that this arrangement causes too much traffic
* between d and i-caches and that we need to carve up the structure differently.
*/
class Fragment : public avmplus::GCFinalizedObject
class Fragment
{
public:
Fragment(const void*);