mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 929236 - Don't waste time caching small asm.js modules (r=sstangl)
--HG-- extra : rebase_source : 03c1f15c9ad89e0cae2e53a633ab743656380bf5
This commit is contained in:
parent
5ed834b091
commit
3d01d25dc6
@ -1023,12 +1023,22 @@ OpenFile(JS::Handle<JSObject*> aGlobal,
|
||||
typedef uint32_t AsmJSCookieType;
|
||||
static const uint32_t sAsmJSCookie = 0x600d600d;
|
||||
|
||||
// Anything smaller should compile fast enough that caching will just add
|
||||
// overhead.
|
||||
static const size_t sMinCachedModuleLength = 10000;
|
||||
|
||||
bool
|
||||
OpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t* aFile)
|
||||
{
|
||||
if (size_t(aLimit - aBegin) < sMinCachedModuleLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File::AutoClose file;
|
||||
if (!OpenFile(aGlobal, eOpenForRead, 0, &file)) {
|
||||
return false;
|
||||
@ -1073,10 +1083,16 @@ CloseEntryForRead(JS::Handle<JSObject*> global,
|
||||
|
||||
bool
|
||||
OpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aFile)
|
||||
{
|
||||
if (size_t(aEnd - aBegin) < sMinCachedModuleLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add extra space for the AsmJSCookieType (see OpenEntryForRead).
|
||||
aSize += sizeof(AsmJSCookieType);
|
||||
|
||||
|
@ -35,17 +35,29 @@ enum OpenMode
|
||||
// Implementation of AsmJSCacheOps, installed by nsJSEnvironment:
|
||||
|
||||
bool
|
||||
OpenEntryForRead(JS::Handle<JSObject*> aGlobal, size_t* aSize,
|
||||
const uint8_t** aMemory, intptr_t *aHandle);
|
||||
OpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t *aHandle);
|
||||
void
|
||||
CloseEntryForRead(JS::Handle<JSObject*> aGlobal, size_t aSize,
|
||||
const uint8_t* aMemory, intptr_t aHandle);
|
||||
CloseEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
size_t aSize,
|
||||
const uint8_t* aMemory,
|
||||
intptr_t aHandle);
|
||||
bool
|
||||
OpenEntryForWrite(JS::Handle<JSObject*> aGlobal, size_t aSize,
|
||||
uint8_t** aMemory, intptr_t* aHandle);
|
||||
OpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aHandle);
|
||||
void
|
||||
CloseEntryForWrite(JS::Handle<JSObject*> aGlobal, size_t aSize,
|
||||
uint8_t* aMemory, intptr_t aHandle);
|
||||
CloseEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
size_t aSize,
|
||||
uint8_t* aMemory,
|
||||
intptr_t aHandle);
|
||||
bool
|
||||
GetBuildId(js::Vector<char>* aBuildId);
|
||||
|
||||
|
@ -1632,7 +1632,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
module_->exportedFunction(exportIndex).initCodeOffset(masm_.size());
|
||||
}
|
||||
|
||||
void buildCompilationTimeReport(ScopedJSFreePtr<char> *out) {
|
||||
void buildCompilationTimeReport(bool storedInCache, ScopedJSFreePtr<char> *out) {
|
||||
ScopedJSFreePtr<char> slowFuns;
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
int64_t usecAfter = PRMJ_Now();
|
||||
@ -1653,8 +1653,10 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
return;
|
||||
}
|
||||
}
|
||||
out->reset(JS_smprintf("total compilation time %dms%s",
|
||||
msTotal, slowFuns ? slowFuns.get() : ""));
|
||||
out->reset(JS_smprintf("total compilation time %dms%s%s",
|
||||
msTotal,
|
||||
storedInCache ? "; stored in cache" : "",
|
||||
slowFuns ? slowFuns.get() : ""));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -6462,10 +6464,10 @@ CheckModule(ExclusiveContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
if (!FinishModule(m, &module, &linkData))
|
||||
return false;
|
||||
|
||||
StoreAsmJSModuleInCache(parser, *module, linkData, cx);
|
||||
bool storedInCache = StoreAsmJSModuleInCache(parser, *module, linkData, cx);
|
||||
module->staticallyLink(linkData, cx);
|
||||
|
||||
m.buildCompilationTimeReport(compilationTimeReport);
|
||||
m.buildCompilationTimeReport(storedInCache, compilationTimeReport);
|
||||
*moduleOut = module.forget();
|
||||
return true;
|
||||
}
|
||||
|
@ -802,6 +802,14 @@ class ModuleChars
|
||||
Vector<PropertyNameWrapper, 0, SystemAllocPolicy> funCtorArgs_;
|
||||
|
||||
public:
|
||||
static uint32_t beginOffset(AsmJSParser &parser) {
|
||||
return parser.pc->maybeFunction->pn_pos.begin;
|
||||
}
|
||||
|
||||
static uint32_t endOffset(AsmJSParser &parser) {
|
||||
return parser.tokenStream.peekTokenPos().end;
|
||||
}
|
||||
|
||||
bool initFromParsedModule(AsmJSParser &parser, const AsmJSModule &module) {
|
||||
// For a function statement or named function expression:
|
||||
// function f(x,y,z) { abc }
|
||||
@ -815,11 +823,9 @@ class ModuleChars
|
||||
// For functions created with 'new Function', function arguments are
|
||||
// not present in the source so we must manually explicitly serialize
|
||||
// and match the formals as a Vector of PropertyName.
|
||||
uint32_t beginOffset = parser.pc->maybeFunction->pn_pos.begin;
|
||||
uint32_t endOffset = parser.tokenStream.peekTokenPos().end;
|
||||
JS_ASSERT(beginOffset < endOffset);
|
||||
begin_ = parser.tokenStream.rawBase() + beginOffset;
|
||||
length_ = endOffset - beginOffset;
|
||||
JS_ASSERT(beginOffset(parser) < endOffset(parser));
|
||||
begin_ = parser.tokenStream.rawBase() + beginOffset(parser);
|
||||
length_ = endOffset(parser) - beginOffset(parser);
|
||||
isFunCtor_ = parser.pc->isFunctionConstructorBody();
|
||||
if (isFunCtor_) {
|
||||
unsigned numArgs;
|
||||
@ -858,9 +864,8 @@ class ModuleChars
|
||||
return cursor;
|
||||
}
|
||||
|
||||
bool matchUnparsedModule(const AsmJSParser &parser) const {
|
||||
uint32_t parseBeginOffset = parser.pc->maybeFunction->pn_pos.begin;
|
||||
const jschar *parseBegin = parser.tokenStream.rawBase() + parseBeginOffset;
|
||||
bool matchUnparsedModule(AsmJSParser &parser) const {
|
||||
const jschar *parseBegin = parser.tokenStream.rawBase() + beginOffset(parser);
|
||||
const jschar *parseLimit = parser.tokenStream.rawLimit();
|
||||
JS_ASSERT(parseLimit >= parseBegin);
|
||||
if (uint32_t(parseLimit - parseBegin) < length_)
|
||||
@ -909,7 +914,7 @@ struct ScopedCacheEntryOpenedForWrite
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
js::StoreAsmJSModuleInCache(AsmJSParser &parser,
|
||||
const AsmJSModule &module,
|
||||
const AsmJSStaticLinkData &linkData,
|
||||
@ -917,24 +922,27 @@ js::StoreAsmJSModuleInCache(AsmJSParser &parser,
|
||||
{
|
||||
MachineId machineId(cx);
|
||||
if (!machineId.extractCurrentState(cx))
|
||||
return;
|
||||
return false;
|
||||
|
||||
ModuleChars moduleChars;
|
||||
if (!moduleChars.initFromParsedModule(parser, module))
|
||||
return;
|
||||
return false;
|
||||
|
||||
size_t serializedSize = machineId.serializedSize() +
|
||||
moduleChars.serializedSize() +
|
||||
module.serializedSize() +
|
||||
linkData.serializedSize();
|
||||
|
||||
JS::OpenAsmJSCacheEntryForWriteOp openEntryForWrite = cx->asmJSCacheOps().openEntryForWrite;
|
||||
if (!openEntryForWrite)
|
||||
return;
|
||||
JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite;
|
||||
if (!open)
|
||||
return false;
|
||||
|
||||
const jschar *begin = parser.tokenStream.rawBase() + ModuleChars::beginOffset(parser);
|
||||
const jschar *end = parser.tokenStream.rawBase() + ModuleChars::endOffset(parser);
|
||||
|
||||
ScopedCacheEntryOpenedForWrite entry(cx, serializedSize);
|
||||
if (!openEntryForWrite(cx->global(), entry.serializedSize, &entry.memory, &entry.handle))
|
||||
return;
|
||||
if (!open(cx->global(), begin, end, entry.serializedSize, &entry.memory, &entry.handle))
|
||||
return false;
|
||||
|
||||
uint8_t *cursor = entry.memory;
|
||||
cursor = machineId.serialize(cursor);
|
||||
@ -943,6 +951,7 @@ js::StoreAsmJSModuleInCache(AsmJSParser &parser,
|
||||
cursor = linkData.serialize(cursor);
|
||||
|
||||
JS_ASSERT(cursor == entry.memory + serializedSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ScopedCacheEntryOpenedForRead
|
||||
@ -974,12 +983,15 @@ js::LookupAsmJSModuleInCache(ExclusiveContext *cx,
|
||||
if (!machineId.extractCurrentState(cx))
|
||||
return true;
|
||||
|
||||
JS::OpenAsmJSCacheEntryForReadOp openEntryForRead = cx->asmJSCacheOps().openEntryForRead;
|
||||
if (!openEntryForRead)
|
||||
JS::OpenAsmJSCacheEntryForReadOp open = cx->asmJSCacheOps().openEntryForRead;
|
||||
if (!open)
|
||||
return true;
|
||||
|
||||
const jschar *begin = parser.tokenStream.rawBase() + ModuleChars::beginOffset(parser);
|
||||
const jschar *limit = parser.tokenStream.rawLimit();
|
||||
|
||||
ScopedCacheEntryOpenedForRead entry(cx);
|
||||
if (!openEntryForRead(cx->global(), &entry.serializedSize, &entry.memory, &entry.handle))
|
||||
if (!open(cx->global(), begin, limit, &entry.serializedSize, &entry.memory, &entry.handle))
|
||||
return true;
|
||||
|
||||
const uint8_t *cursor = entry.memory;
|
||||
|
@ -776,7 +776,7 @@ class AsmJSModule
|
||||
};
|
||||
|
||||
// Store the just-parsed module in the cache using AsmJSCacheOps.
|
||||
extern void
|
||||
extern bool
|
||||
StoreAsmJSModuleInCache(AsmJSParser &parser,
|
||||
const AsmJSModule &module,
|
||||
const AsmJSStaticLinkData &linkData,
|
||||
|
@ -4605,30 +4605,32 @@ namespace JS {
|
||||
|
||||
/*
|
||||
* This callback represents a request by the JS engine to open for reading the
|
||||
* existing cache entry for the given global. If a cache entry exists, the
|
||||
* callback shall return 'true' and return the size, base address and an opaque
|
||||
* file handle as outparams. If the callback returns 'true', the JS engine
|
||||
* guarantees a call to CloseAsmJSCacheEntryForReadOp, passing the same base
|
||||
* address, size and handle.
|
||||
* existing cache entry for the given global and char range that may contain a
|
||||
* module. If a cache entry exists, the callback shall return 'true' and return
|
||||
* the size, base address and an opaque file handle as outparams. If the
|
||||
* callback returns 'true', the JS engine guarantees a call to
|
||||
* CloseAsmJSCacheEntryForReadOp, passing the same base address, size and
|
||||
* handle.
|
||||
*/
|
||||
typedef bool
|
||||
(* OpenAsmJSCacheEntryForReadOp)(HandleObject global, size_t *size, const uint8_t **memory,
|
||||
intptr_t *handle);
|
||||
(* OpenAsmJSCacheEntryForReadOp)(HandleObject global, const jschar *begin, const jschar *limit,
|
||||
size_t *size, const uint8_t **memory, intptr_t *handle);
|
||||
typedef void
|
||||
(* CloseAsmJSCacheEntryForReadOp)(HandleObject global, size_t size, const uint8_t *memory,
|
||||
intptr_t handle);
|
||||
|
||||
/*
|
||||
* This callback represents a request by the JS engine to open for writing a
|
||||
* cache entry of the given size for the given global. If cache entry space is
|
||||
* available, the callback shall return 'true' and return the base address and
|
||||
* an opaque file handle as outparams. If the callback returns 'true', the JS
|
||||
* engine guarantees a call to CloseAsmJSCacheEntryForWriteOp passing the same
|
||||
* base address, size and handle.
|
||||
* cache entry of the given size for the given global and char range containing
|
||||
* the just-compiled module. If cache entry space is available, the callback
|
||||
* shall return 'true' and return the base address and an opaque file handle as
|
||||
* outparams. If the callback returns 'true', the JS engine guarantees a call
|
||||
* to CloseAsmJSCacheEntryForWriteOp passing the same base address, size and
|
||||
* handle.
|
||||
*/
|
||||
typedef bool
|
||||
(* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, size_t size, uint8_t **memory,
|
||||
intptr_t *handle);
|
||||
(* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, const jschar *begin, const jschar *end,
|
||||
size_t size, uint8_t **memory, intptr_t *handle);
|
||||
typedef void
|
||||
(* CloseAsmJSCacheEntryForWriteOp)(HandleObject global, size_t size, uint8_t *memory,
|
||||
intptr_t handle);
|
||||
|
@ -5015,8 +5015,9 @@ class ScopedFileDesc
|
||||
static const uint32_t asmJSCacheCookie = 0xabbadaba;
|
||||
|
||||
static bool
|
||||
ShellOpenAsmJSCacheEntryForRead(HandleObject global, size_t *serializedSizeOut,
|
||||
const uint8_t **memoryOut, intptr_t *handleOut)
|
||||
ShellOpenAsmJSCacheEntryForRead(HandleObject global, const jschar *begin, const jschar *limit,
|
||||
size_t *serializedSizeOut, const uint8_t **memoryOut,
|
||||
intptr_t *handleOut)
|
||||
{
|
||||
if (!jsCacheAsmJSPath)
|
||||
return false;
|
||||
@ -5087,8 +5088,8 @@ ShellCloseAsmJSCacheEntryForRead(HandleObject global, size_t serializedSize, con
|
||||
}
|
||||
|
||||
static bool
|
||||
ShellOpenAsmJSCacheEntryForWrite(HandleObject global, size_t serializedSize,
|
||||
uint8_t **memoryOut, intptr_t *handleOut)
|
||||
ShellOpenAsmJSCacheEntryForWrite(HandleObject global, const jschar *begin, const jschar *end,
|
||||
size_t serializedSize, uint8_t **memoryOut, intptr_t *handleOut)
|
||||
{
|
||||
if (!jsCacheAsmJSPath)
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user