diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 0cf09b001a8..a7b0f729103 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -92,7 +92,8 @@ JSCompartment::JSCompartment(JSRuntime *rt) debugModeBits(rt->debugMode ? DebugFromC : 0), mathCache(NULL), watchpointMap(NULL), - scriptCountsMap(NULL) + scriptCountsMap(NULL), + sourceMapMap(NULL) { PodArrayZero(evalCache); setGCMaxMallocBytes(rt->gcMaxMallocBytes * 0.9); @@ -113,6 +114,7 @@ JSCompartment::~JSCompartment() Foreground::delete_(mathCache); Foreground::delete_(watchpointMap); Foreground::delete_(scriptCountsMap); + Foreground::delete_(sourceMapMap); #ifdef DEBUG for (size_t i = 0; i < ArrayLength(evalCache); ++i) diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index ffa038377be..139c2c37765 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -465,6 +465,8 @@ struct JSCompartment js::WatchpointMap *watchpointMap; js::ScriptCountsMap *scriptCountsMap; + + js::SourceMapMap *sourceMapMap; }; #define JS_PROPERTY_TREE(cx) ((cx)->compartment->propertyTree) diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 728f4dc3b02..1277515dd7e 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -687,7 +687,7 @@ JS_GetScriptFilename(JSContext *cx, JSScript *script) JS_PUBLIC_API(const jschar *) JS_GetScriptSourceMap(JSContext *cx, JSScript *script) { - return script->sourceMap; + return script->hasSourceMap ? script->getSourceMap() : NULL; } JS_PUBLIC_API(unsigned) diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index f784e84efdd..24e5628a96a 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -880,6 +880,62 @@ JSScript::destroyScriptCounts(FreeOp *fop) } } +bool +JSScript::setSourceMap(JSContext *cx, jschar *sourceMap) +{ + JS_ASSERT(!hasSourceMap); + + /* Create compartment's sourceMapMap if necessary. */ + SourceMapMap *map = compartment()->sourceMapMap; + if (!map) { + map = cx->new_(); + if (!map || !map->init()) { + cx->delete_(map); + return false; + } + compartment()->sourceMapMap = map; + } + + if (!map->putNew(this, sourceMap)) { + cx->delete_(map); + return false; + } + hasSourceMap = true; // safe to set this; we can't fail after this point + + return true; +} + +jschar * +JSScript::getSourceMap() { + JS_ASSERT(hasSourceMap); + SourceMapMap *map = compartment()->sourceMapMap; + JS_ASSERT(map); + SourceMapMap::Ptr p = map->lookup(this); + JS_ASSERT(p); + return p->value; +} + +jschar * +JSScript::releaseSourceMap() +{ + JS_ASSERT(hasSourceMap); + SourceMapMap *map = compartment()->sourceMapMap; + JS_ASSERT(map); + SourceMapMap::Ptr p = map->lookup(this); + JS_ASSERT(p); + jschar *sourceMap = p->value; + map->remove(p); + hasSourceMap = false; + return sourceMap; +} + +void +JSScript::destroySourceMap(FreeOp *fop) +{ + if (hasSourceMap) + fop->free_(releaseSourceMap()); +} + /* * Shared script filename management. */ @@ -1287,7 +1343,13 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) if (script->originPrincipals) JS_HoldPrincipals(script->originPrincipals); - script->sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap(); + jschar *sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap(); + if (sourceMap) { + if (!script->setSourceMap(cx, sourceMap)) { + cx->free_(sourceMap); + return NULL; + } + } if (!FinishTakingSrcNotes(cx, bce, script->notes())) return NULL; @@ -1458,9 +1520,7 @@ JSScript::finalize(FreeOp *fop) #endif destroyScriptCounts(fop); - - if (sourceMap) - fop->free_(sourceMap); + destroySourceMap(fop); if (debug) { jsbytecode *end = code + length; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index d0fcdb1f418..38dd676d395 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -319,6 +319,11 @@ typedef HashMap, SystemAllocPolicy> ScriptCountsMap; +typedef HashMap, + SystemAllocPolicy> SourceMapMap; + class DebugScript { friend struct ::JSScript; @@ -421,8 +426,6 @@ struct JSScript : public js::gc::Cell JSPrincipals *principals;/* principals for this script */ JSPrincipals *originPrincipals; /* see jsapi.h 'originPrincipals' comment */ - jschar *sourceMap; /* source map file or null */ - /* * A global object for the script. * - All scripts returned by JSAPI functions (JS_CompileScript, @@ -469,13 +472,8 @@ struct JSScript : public js::gc::Cell // Unique identifier within the compartment for this script, used for // printing analysis information. uint32_t id_; - #if JS_BITS_PER_WORD == 64 private: - uint32_t idpad64; - #endif -#elif JS_BITS_PER_WORD == 32 - private: - uint32_t pad32; + uint32_t idpad; #endif // 16-bit fields. @@ -544,6 +542,8 @@ struct JSScript : public js::gc::Cell bool isGenerator:1; /* is a generator */ bool hasScriptCounts:1;/* script has an entry in JSCompartment::scriptCountsMap */ + bool hasSourceMap:1; /* script has an entry in + JSCompartment::sourceMapMap */ private: /* See comments below. */ @@ -695,12 +695,16 @@ struct JSScript : public js::gc::Cell #endif public: - js::PCCounts getPCCounts(jsbytecode *pc); - bool initScriptCounts(JSContext *cx); + js::PCCounts getPCCounts(jsbytecode *pc); js::ScriptCounts releaseScriptCounts(); void destroyScriptCounts(js::FreeOp *fop); + bool setSourceMap(JSContext *cx, jschar *sourceMap); + jschar *getSourceMap(); + jschar *releaseSourceMap(); + void destroySourceMap(js::FreeOp *fop); + jsbytecode *main() { return code + mainOffset; }