mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-18 17:02:01 +00:00
Bug 511237 - Remove primary use of Fragmento from jsregexp, r=dmandelin.
This commit is contained in:
parent
e063ca411e
commit
0ca6c5eb09
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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*);
|
||||
|
Loading…
x
Reference in New Issue
Block a user