зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1459067 - Part 1: Allow storing BinASTSource in ScriptSource. (r=jorendorff)
--HG-- extra : rebase_source : 4a46ad0a57c3b6a79bd2783ab93a5f9218d58056
This commit is contained in:
Родитель
92171122b5
Коммит
4c746e2845
|
@ -676,6 +676,9 @@ frontend::CompileGlobalBinASTScript(JSContext* cx, LifoAlloc& alloc, const ReadO
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!sourceObj->source()->setBinASTSourceCopy(cx, src, len))
|
||||
return nullptr;
|
||||
|
||||
RootedScript script(cx, JSScript::Create(cx, options, sourceObj, 0, len, 0, len));
|
||||
|
||||
if (!script) {
|
||||
|
|
|
@ -4102,7 +4102,7 @@ JS_DecompileScript(JSContext* cx, HandleScript script)
|
|||
if (fun) {
|
||||
return JS_DecompileFunction(cx, fun);
|
||||
}
|
||||
bool haveSource = script->scriptSource()->hasSourceData();
|
||||
bool haveSource = script->scriptSource()->hasSourceText();
|
||||
if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -7800,11 +7800,11 @@ class DebuggerSourceGetTextMatcher
|
|||
|
||||
ReturnType match(HandleScriptSourceObject sourceObject) {
|
||||
ScriptSource* ss = sourceObject->source();
|
||||
bool hasSourceData = ss->hasSourceData();
|
||||
if (!ss->hasSourceData() && !JSScript::loadSource(cx_, ss, &hasSourceData)) {
|
||||
bool hasSourceText = ss->hasSourceText();
|
||||
if (!ss->hasSourceText() && !JSScript::loadSource(cx_, ss, &hasSourceText)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!hasSourceData) {
|
||||
if (!hasSourceText) {
|
||||
return NewStringCopyZ<CanGC>(cx_, "[no source]");
|
||||
}
|
||||
|
||||
|
|
|
@ -1051,7 +1051,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource)
|
|||
// that eval returns lambda, not function statement.
|
||||
bool addParentheses = haveSource && isToSource && (fun->isLambda() && !fun->isArrow());
|
||||
|
||||
if (haveSource && !script->scriptSource()->hasSourceData() &&
|
||||
if (haveSource && !script->scriptSource()->hasSourceText() &&
|
||||
!JSScript::loadSource(cx, script->scriptSource(), &haveSource))
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -1783,7 +1783,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
|
|||
|
||||
// This is lazy canonical-function.
|
||||
|
||||
MOZ_ASSERT(lazy->scriptSource()->hasSourceData());
|
||||
MOZ_ASSERT(lazy->scriptSource()->hasSourceText());
|
||||
|
||||
// Parse and compile the script from source.
|
||||
size_t lazyLength = lazy->sourceEnd() - lazy->sourceStart();
|
||||
|
|
|
@ -1543,7 +1543,7 @@ ScriptSourceObject::initElementProperties(JSContext* cx, HandleScriptSourceObjec
|
|||
/* static */ bool
|
||||
JSScript::loadSource(JSContext* cx, ScriptSource* ss, bool* worked)
|
||||
{
|
||||
MOZ_ASSERT(!ss->hasSourceData());
|
||||
MOZ_ASSERT(!ss->hasSourceText());
|
||||
*worked = false;
|
||||
if (!cx->runtime()->sourceHook.ref() || !ss->sourceRetrievable()) {
|
||||
return true;
|
||||
|
@ -1567,14 +1567,14 @@ JSScript::loadSource(JSContext* cx, ScriptSource* ss, bool* worked)
|
|||
/* static */ JSFlatString*
|
||||
JSScript::sourceData(JSContext* cx, HandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(script->scriptSource()->hasSourceData());
|
||||
MOZ_ASSERT(script->scriptSource()->hasSourceText());
|
||||
return script->scriptSource()->substring(cx, script->sourceStart(), script->sourceEnd());
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::appendSourceDataForToString(JSContext* cx, StringBuffer& buf)
|
||||
{
|
||||
MOZ_ASSERT(scriptSource()->hasSourceData());
|
||||
MOZ_ASSERT(scriptSource()->hasSourceText());
|
||||
return scriptSource()->appendSubstring(cx, buf, toStringStart(), toStringEnd());
|
||||
}
|
||||
|
||||
|
@ -1936,6 +1936,45 @@ ScriptSource::setSource(JSContext* cx, UniqueTwoByteChars&& source, size_t lengt
|
|||
return true;
|
||||
}
|
||||
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
ScriptSource::setBinASTSourceCopy(JSContext* cx, const uint8_t* buf, size_t len)
|
||||
{
|
||||
auto &cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings();
|
||||
auto deduped = cache.getOrCreate(reinterpret_cast<const char *>(buf), len);
|
||||
if (!deduped) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(data.is<Missing>());
|
||||
data = SourceType(BinAST(std::move(*deduped)));
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
ScriptSource::setBinASTSource(JSContext* cx, UniqueChars&& buf, size_t len)
|
||||
{
|
||||
auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings();
|
||||
auto deduped = cache.getOrCreate(std::move(buf), len);
|
||||
if (!deduped) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(data.is<Missing>());
|
||||
data = SourceType(BinAST(std::move(*deduped)));
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t*
|
||||
ScriptSource::binASTSource()
|
||||
{
|
||||
MOZ_ASSERT(hasBinASTSource());
|
||||
return reinterpret_cast<const uint8_t*>(data.as<BinAST>().string.chars());
|
||||
}
|
||||
|
||||
#endif /* JS_BUILD_BINAST */
|
||||
|
||||
void
|
||||
ScriptSource::setSource(SharedImmutableTwoByteString&& string)
|
||||
{
|
||||
|
@ -2021,7 +2060,7 @@ ScriptSource::setCompressedSource(SharedImmutableString&& raw, size_t uncompress
|
|||
bool
|
||||
ScriptSource::setSourceCopy(JSContext* cx, SourceBufferHolder& srcBuf)
|
||||
{
|
||||
MOZ_ASSERT(!hasSourceData());
|
||||
MOZ_ASSERT(!hasSourceText());
|
||||
|
||||
JSRuntime* runtime = cx->zone()->runtimeFromAnyThread();
|
||||
auto& cache = runtime->sharedImmutableStrings();
|
||||
|
@ -2239,6 +2278,10 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
return c.raw.length();
|
||||
}
|
||||
|
||||
size_t match(BinAST&) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t match(Missing&) {
|
||||
MOZ_CRASH("Missing source data in ScriptSource::performXDR");
|
||||
return 0;
|
||||
|
@ -2255,20 +2298,27 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
return (void*) c.raw.chars();
|
||||
}
|
||||
|
||||
void* match(BinAST& b) {
|
||||
return (void*) b.string.chars();
|
||||
}
|
||||
|
||||
void* match(Missing&) {
|
||||
MOZ_CRASH("Missing source data in ScriptSource::performXDR");
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t hasSource = hasSourceData();
|
||||
uint8_t hasSource = hasSourceText();
|
||||
MOZ_TRY(xdr->codeUint8(&hasSource));
|
||||
|
||||
uint8_t hasBinSource = hasBinASTSource();
|
||||
MOZ_TRY(xdr->codeUint8(&hasBinSource));
|
||||
|
||||
uint8_t retrievable = sourceRetrievable_;
|
||||
MOZ_TRY(xdr->codeUint8(&retrievable));
|
||||
sourceRetrievable_ = retrievable;
|
||||
|
||||
if (hasSource && !sourceRetrievable_) {
|
||||
if ((hasSource || hasBinSource) && !sourceRetrievable_) {
|
||||
uint32_t len = 0;
|
||||
if (mode == XDR_ENCODE) {
|
||||
len = length();
|
||||
|
@ -2282,7 +2332,7 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
}
|
||||
MOZ_TRY(xdr->codeUint32(&compressedLength));
|
||||
|
||||
size_t byteLen = compressedLength ? compressedLength : (len * sizeof(char16_t));
|
||||
size_t byteLen = hasBinSource ? len : compressedLength ? compressedLength : (len * sizeof(char16_t));
|
||||
if (mode == XDR_DECODE) {
|
||||
auto bytes = xdr->cx()->template make_pod_array<char>(Max<size_t>(byteLen, 1));
|
||||
if (!bytes) {
|
||||
|
@ -2290,7 +2340,16 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
}
|
||||
MOZ_TRY(xdr->codeBytes(bytes.get(), byteLen));
|
||||
|
||||
if (compressedLength) {
|
||||
if (hasBinSource) {
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
if (!setBinASTSource(xdr->cx(), std::move(bytes), len)) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
#else
|
||||
MOZ_ASSERT(mode != XDR_ENCODE);
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
#endif /* JS_BUILD_BINAST */
|
||||
} else if (compressedLength) {
|
||||
if (!setCompressedSource(xdr->cx(), std::move(bytes), byteLen, len)) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -2367,7 +2426,7 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
}
|
||||
|
||||
// Note the content of sources decoded when recording or replaying.
|
||||
if (mode == XDR_DECODE && hasSourceData() && mozilla::recordreplay::IsRecordingOrReplaying()) {
|
||||
if (mode == XDR_DECODE && hasSourceText() && mozilla::recordreplay::IsRecordingOrReplaying()) {
|
||||
UncompressedSourceCache::AutoHoldEntry holder;
|
||||
ScriptSource::PinnedChars chars(xdr->cx(), this, holder, 0, length());
|
||||
if (!chars.get()) {
|
||||
|
|
|
@ -430,7 +430,15 @@ class ScriptSource
|
|||
{ }
|
||||
};
|
||||
|
||||
using SourceType = mozilla::Variant<Missing, Uncompressed, Compressed>;
|
||||
struct BinAST
|
||||
{
|
||||
SharedImmutableString string;
|
||||
explicit BinAST(SharedImmutableString&& str)
|
||||
: string(std::move(str))
|
||||
{ }
|
||||
};
|
||||
|
||||
using SourceType = mozilla::Variant<Missing, Uncompressed, Compressed, BinAST>;
|
||||
SourceType data;
|
||||
|
||||
// If the GC attempts to call setCompressedSource with PinnedChars
|
||||
|
@ -495,7 +503,7 @@ class ScriptSource
|
|||
mozilla::TimeStamp parseEnded_;
|
||||
|
||||
// True if we can call JSRuntime::sourceHook to load the source on
|
||||
// demand. If sourceRetrievable_ and hasSourceData() are false, it is not
|
||||
// demand. If sourceRetrievable_ and hasSourceText() are false, it is not
|
||||
// possible to get source at all.
|
||||
bool sourceRetrievable_:1;
|
||||
bool hasIntroductionOffset_:1;
|
||||
|
@ -555,7 +563,8 @@ class ScriptSource
|
|||
MOZ_MUST_USE bool setSourceCopy(JSContext* cx, JS::SourceBufferHolder& srcBuf);
|
||||
void setSourceRetrievable() { sourceRetrievable_ = true; }
|
||||
bool sourceRetrievable() const { return sourceRetrievable_; }
|
||||
bool hasSourceData() const { return !data.is<Missing>(); }
|
||||
bool hasSourceText() const { return hasUncompressedSource() || hasCompressedSource(); }
|
||||
bool hasBinASTSource() const { return data.is<BinAST>(); }
|
||||
bool hasUncompressedSource() const { return data.is<Uncompressed>(); }
|
||||
bool hasCompressedSource() const { return data.is<Compressed>(); }
|
||||
|
||||
|
@ -570,13 +579,17 @@ class ScriptSource
|
|||
return c.uncompressedLength;
|
||||
}
|
||||
|
||||
size_t match(const BinAST& b) {
|
||||
return b.string.length();
|
||||
}
|
||||
|
||||
size_t match(const Missing& m) {
|
||||
MOZ_CRASH("ScriptSource::length on a missing source");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
MOZ_ASSERT(hasSourceData());
|
||||
MOZ_ASSERT(hasSourceText() || hasBinASTSource());
|
||||
return data.match(LengthMatcher());
|
||||
}
|
||||
|
||||
|
@ -606,6 +619,25 @@ class ScriptSource
|
|||
size_t sourceLength);
|
||||
void setCompressedSource(SharedImmutableString&& raw, size_t sourceLength);
|
||||
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
||||
/*
|
||||
* Do not take ownership of the given `buf`. Store the canonical, shared
|
||||
* and de-duplicated version. If there is no extant shared version of
|
||||
* `buf`, make a copy.
|
||||
*/
|
||||
MOZ_MUST_USE bool setBinASTSourceCopy(JSContext* cx, const uint8_t* buf, size_t len);
|
||||
|
||||
/*
|
||||
* Take ownership of the given `buf` and return the canonical, shared and
|
||||
* de-duplicated version.
|
||||
*/
|
||||
MOZ_MUST_USE bool setBinASTSource(JSContext* cx, UniqueChars&& buf, size_t len);
|
||||
|
||||
const uint8_t* binASTSource();
|
||||
|
||||
#endif /* JS_BUILD_BINAST */
|
||||
|
||||
// XDR handling
|
||||
template <XDRMode mode>
|
||||
MOZ_MUST_USE XDRResult performXDR(XDRState<mode>* xdr);
|
||||
|
|
|
@ -6682,7 +6682,7 @@ HandleInstantiationFailure(JSContext* cx, CallArgs args, const AsmJSMetadata& me
|
|||
|
||||
// Source discarding is allowed to affect JS semantics because it is never
|
||||
// enabled for normal JS content.
|
||||
bool haveSource = source->hasSourceData();
|
||||
bool haveSource = source->hasSourceText();
|
||||
if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -7618,7 +7618,7 @@ js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool isToSource)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool haveSource = source->hasSourceData();
|
||||
bool haveSource = source->hasSourceText();
|
||||
if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -7669,7 +7669,7 @@ js::AsmJSFunctionToString(JSContext* cx, HandleFunction fun)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool haveSource = source->hasSourceData();
|
||||
bool haveSource = source->hasSourceText();
|
||||
if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче