mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 702426: Hoist executable allocator for better RegExp code sharing. (r=luke)
--HG-- extra : rebase_source : fa6c50980d6b0539064140567ddaddab45341a49
This commit is contained in:
parent
f784d8150d
commit
90f6a5f8e1
@ -724,6 +724,7 @@ JSRuntime::JSRuntime()
|
||||
#ifdef JS_THREADSAFE
|
||||
interruptCounter(0),
|
||||
#endif
|
||||
threadData(thisFromCtor()),
|
||||
trustedPrincipals_(NULL),
|
||||
shapeGen(0),
|
||||
wrapObjectCallback(NULL),
|
||||
|
@ -87,6 +87,7 @@
|
||||
#endif
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "frontend/ParseMaps.h"
|
||||
#include "yarr/BumpPointerAllocator.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jscntxtinlines.h"
|
||||
@ -98,8 +99,9 @@ using namespace js::gc;
|
||||
|
||||
namespace js {
|
||||
|
||||
ThreadData::ThreadData()
|
||||
: interruptFlags(0),
|
||||
ThreadData::ThreadData(JSRuntime *rt)
|
||||
: rt(rt),
|
||||
interruptFlags(0),
|
||||
#ifdef JS_THREADSAFE
|
||||
requestDepth(0),
|
||||
#endif
|
||||
@ -111,6 +113,8 @@ ThreadData::ThreadData()
|
||||
#endif
|
||||
waiveGCQuota(false),
|
||||
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
execAlloc(NULL),
|
||||
bumpAlloc(NULL),
|
||||
repCache(NULL),
|
||||
dtoaState(NULL),
|
||||
nativeStackBase(GetNativeStackBase()),
|
||||
@ -126,6 +130,9 @@ ThreadData::~ThreadData()
|
||||
{
|
||||
JS_ASSERT(!repCache);
|
||||
|
||||
rt->delete_<JSC::ExecutableAllocator>(execAlloc);
|
||||
rt->delete_<WTF::BumpPointerAllocator>(bumpAlloc);
|
||||
|
||||
if (dtoaState)
|
||||
js_DestroyDtoaState(dtoaState);
|
||||
}
|
||||
@ -140,6 +147,8 @@ ThreadData::init()
|
||||
void
|
||||
ThreadData::triggerOperationCallback(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt == this->rt);
|
||||
|
||||
/*
|
||||
* Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures
|
||||
* the write will become immediately visible to other processors polling
|
||||
@ -157,13 +166,40 @@ ThreadData::triggerOperationCallback(JSRuntime *rt)
|
||||
#endif
|
||||
}
|
||||
|
||||
JSC::ExecutableAllocator *
|
||||
ThreadData::createExecutableAllocator(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!execAlloc);
|
||||
JS_ASSERT(cx->runtime == rt);
|
||||
|
||||
execAlloc = rt->new_<JSC::ExecutableAllocator>();
|
||||
if (!execAlloc)
|
||||
js_ReportOutOfMemory(cx);
|
||||
return execAlloc;
|
||||
}
|
||||
|
||||
WTF::BumpPointerAllocator *
|
||||
ThreadData::createBumpPointerAllocator(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!bumpAlloc);
|
||||
JS_ASSERT(cx->runtime == rt);
|
||||
|
||||
bumpAlloc = rt->new_<WTF::BumpPointerAllocator>();
|
||||
if (!bumpAlloc)
|
||||
js_ReportOutOfMemory(cx);
|
||||
return bumpAlloc;
|
||||
}
|
||||
|
||||
RegExpPrivateCache *
|
||||
ThreadData::createRegExpPrivateCache(JSRuntime *rt)
|
||||
ThreadData::createRegExpPrivateCache(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!repCache);
|
||||
JS_ASSERT(cx->runtime == rt);
|
||||
|
||||
RegExpPrivateCache *newCache = rt->new_<RegExpPrivateCache>(rt);
|
||||
|
||||
if (!newCache || !newCache->init()) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
rt->delete_<RegExpPrivateCache>(newCache);
|
||||
return NULL;
|
||||
}
|
||||
@ -173,7 +209,7 @@ ThreadData::createRegExpPrivateCache(JSRuntime *rt)
|
||||
}
|
||||
|
||||
void
|
||||
ThreadData::purgeRegExpPrivateCache(JSRuntime *rt)
|
||||
ThreadData::purgeRegExpPrivateCache()
|
||||
{
|
||||
rt->delete_<RegExpPrivateCache>(repCache);
|
||||
repCache = NULL;
|
||||
@ -355,7 +391,7 @@ js_PurgeThreads_PostGlobalSweep(JSContext *cx)
|
||||
thread->data.purgeRegExpPrivateCache(cx->runtime);
|
||||
}
|
||||
#else
|
||||
cx->runtime->threadData.purgeRegExpPrivateCache(cx->runtime);
|
||||
cx->runtime->threadData.purgeRegExpPrivateCache();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -153,6 +153,8 @@ struct PendingProxyOperation {
|
||||
};
|
||||
|
||||
struct ThreadData {
|
||||
JSRuntime *rt;
|
||||
|
||||
/*
|
||||
* If non-zero, we were been asked to call the operation callback as soon
|
||||
* as possible. If the thread has an active request, this contributes
|
||||
@ -198,23 +200,45 @@ struct ThreadData {
|
||||
LifoAlloc tempLifoAlloc;
|
||||
|
||||
private:
|
||||
js::RegExpPrivateCache *repCache;
|
||||
/*
|
||||
* Both of these allocators are used for regular expression code which is shared at the
|
||||
* thread-data level.
|
||||
*/
|
||||
JSC::ExecutableAllocator *execAlloc;
|
||||
WTF::BumpPointerAllocator *bumpAlloc;
|
||||
js::RegExpPrivateCache *repCache;
|
||||
|
||||
js::RegExpPrivateCache *createRegExpPrivateCache(JSRuntime *rt);
|
||||
JSC::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
|
||||
WTF::BumpPointerAllocator *createBumpPointerAllocator(JSContext *cx);
|
||||
js::RegExpPrivateCache *createRegExpPrivateCache(JSContext *cx);
|
||||
|
||||
public:
|
||||
js::RegExpPrivateCache *getRegExpPrivateCache() { return repCache; }
|
||||
JSC::ExecutableAllocator *getOrCreateExecutableAllocator(JSContext *cx) {
|
||||
if (execAlloc)
|
||||
return execAlloc;
|
||||
|
||||
/* N.B. caller is responsible for reporting OOM. */
|
||||
js::RegExpPrivateCache *getOrCreateRegExpPrivateCache(JSRuntime *rt) {
|
||||
return createExecutableAllocator(cx);
|
||||
}
|
||||
|
||||
WTF::BumpPointerAllocator *getOrCreateBumpPointerAllocator(JSContext *cx) {
|
||||
if (bumpAlloc)
|
||||
return bumpAlloc;
|
||||
|
||||
return createBumpPointerAllocator(cx);
|
||||
}
|
||||
|
||||
js::RegExpPrivateCache *getRegExpPrivateCache() {
|
||||
return repCache;
|
||||
}
|
||||
js::RegExpPrivateCache *getOrCreateRegExpPrivateCache(JSContext *cx) {
|
||||
if (repCache)
|
||||
return repCache;
|
||||
|
||||
return createRegExpPrivateCache(rt);
|
||||
return createRegExpPrivateCache(cx);
|
||||
}
|
||||
|
||||
/* Called at the end of the global GC sweep phase to deallocate repCache memory. */
|
||||
void purgeRegExpPrivateCache(JSRuntime *rt);
|
||||
void purgeRegExpPrivateCache();
|
||||
|
||||
/*
|
||||
* The GSN cache is per thread since even multi-cx-per-thread embeddings
|
||||
@ -240,7 +264,7 @@ struct ThreadData {
|
||||
size_t noGCOrAllocationCheck;
|
||||
#endif
|
||||
|
||||
ThreadData();
|
||||
ThreadData(JSRuntime *rt);
|
||||
~ThreadData();
|
||||
|
||||
bool init();
|
||||
|
@ -87,9 +87,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
hasDebugModeCodeToDrop(false),
|
||||
#ifdef JS_METHODJIT
|
||||
jaegerCompartment_(NULL),
|
||||
#endif
|
||||
#if ENABLE_YARR_JIT
|
||||
regExpAllocator(NULL),
|
||||
#endif
|
||||
propertyTree(thisForCtor()),
|
||||
emptyArgumentsShape(NULL),
|
||||
@ -110,10 +107,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
|
||||
JSCompartment::~JSCompartment()
|
||||
{
|
||||
#if ENABLE_YARR_JIT
|
||||
Foreground::delete_(regExpAllocator);
|
||||
#endif
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
Foreground::delete_(jaegerCompartment_);
|
||||
#endif
|
||||
@ -143,10 +136,6 @@ JSCompartment::init(JSContext *cx)
|
||||
if (!scriptFilenameTable.init())
|
||||
return false;
|
||||
|
||||
regExpAllocator = rt->new_<WTF::BumpPointerAllocator>();
|
||||
if (!regExpAllocator)
|
||||
return false;
|
||||
|
||||
if (!backEdgeTable.init())
|
||||
return false;
|
||||
|
||||
|
@ -53,9 +53,6 @@
|
||||
#pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */
|
||||
#endif
|
||||
|
||||
namespace JSC { class ExecutableAllocator; }
|
||||
namespace WTF { class BumpPointerAllocator; }
|
||||
|
||||
namespace js {
|
||||
|
||||
/* Holds the number of recording attemps for an address. */
|
||||
@ -473,7 +470,6 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||
|
||||
void getMjitCodeStats(size_t& method, size_t& regexp, size_t& unused) const;
|
||||
#endif
|
||||
WTF::BumpPointerAllocator *regExpAllocator;
|
||||
|
||||
/*
|
||||
* Shared scope property tree, and arena-pool for allocating its nodes.
|
||||
|
@ -269,6 +269,18 @@ struct TypeCompartment;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JSC {
|
||||
|
||||
class ExecutableAllocator;
|
||||
|
||||
} /* namespace JSC */
|
||||
|
||||
namespace WTF {
|
||||
|
||||
class BumpPointerAllocator;
|
||||
|
||||
} /* namespace WTF */
|
||||
|
||||
} /* export "C++" */
|
||||
|
||||
#else
|
||||
|
@ -248,7 +248,7 @@ RegExpObject::setSticky(bool enabled)
|
||||
inline RegExpPrivateCache *
|
||||
detail::RegExpPrivate::getOrCreateCache(JSContext *cx)
|
||||
{
|
||||
if (RegExpPrivateCache *cache = cx->threadData()->getOrCreateRegExpPrivateCache(cx->runtime))
|
||||
if (RegExpPrivateCache *cache = cx->threadData()->getOrCreateRegExpPrivateCache(cx))
|
||||
return cache;
|
||||
|
||||
js_ReportOutOfMemory(cx);
|
||||
@ -379,18 +379,27 @@ detail::RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, Token
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (isJITRuntimeEnabled(cx) && !yarrPattern.m_containsBackreferences) {
|
||||
if (!cx->compartment->ensureJaegerCompartmentExists(cx))
|
||||
JSC::ExecutableAllocator *execAlloc = cx->threadData()->getOrCreateExecutableAllocator(cx);
|
||||
if (!execAlloc) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSGlobalData globalData(cx->compartment->jaegerCompartment()->execAlloc());
|
||||
JSGlobalData globalData(execAlloc);
|
||||
jitCompile(yarrPattern, &globalData, codeBlock);
|
||||
if (!codeBlock.isFallBack())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
WTF::BumpPointerAllocator *bumpAlloc = cx->threadData()->getOrCreateBumpPointerAllocator(cx);
|
||||
if (!bumpAlloc) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
codeBlock.setFallBack(true);
|
||||
byteCode = byteCompile(yarrPattern, cx->compartment->regExpAllocator).get();
|
||||
byteCode = byteCompile(yarrPattern, bumpAlloc).get();
|
||||
return true;
|
||||
#else /* !defined(ENABLE_YARR_JIT) */
|
||||
int error = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user