Bug 1475228 - Allocate script loader source buffers on the JS heap and pass ownership when compiling r=baku

This commit is contained in:
Jon Coppeard 2018-07-17 14:30:24 +01:00
Родитель d3c569854b
Коммит b64ad562af
4 изменённых файлов: 37 добавлений и 21 удалений

Просмотреть файл

@ -119,12 +119,15 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t haveRead = mRequest->ScriptText().length();
// Reference to the script source buffer which we will update.
ScriptLoadRequest::ScriptTextBuffer& scriptText = mRequest->ScriptText();
uint32_t haveRead = scriptText.length();
CheckedInt<uint32_t> capacity = haveRead;
capacity += needed.value();
if (!capacity.isValid() || !mRequest->ScriptText().reserve(capacity.value())) {
if (!capacity.isValid() || !scriptText.resize(capacity.value())) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -134,7 +137,7 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
bool hadErrors;
Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
MakeSpan(aData, aDataLength),
MakeSpan(mRequest->ScriptText().begin() + haveRead, needed.value()),
MakeSpan(scriptText.begin() + haveRead, needed.value()),
aEndOfStream);
MOZ_ASSERT(result == kInputEmpty);
MOZ_ASSERT(read == aDataLength);
@ -143,7 +146,8 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
haveRead += written;
MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
MOZ_ALWAYS_TRUE(mRequest->ScriptText().resizeUninitialized(haveRead));
MOZ_ALWAYS_TRUE(scriptText.resize(haveRead));
mRequest->mScriptTextLength = scriptText.length();
return NS_OK;
}

Просмотреть файл

@ -66,6 +66,7 @@ ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
, mWasCompiledOMT(false)
, mIsTracking(false)
, mOffThreadToken(nullptr)
, mScriptTextLength(0)
, mScriptBytecode()
, mBytecodeOffset(0)
, mURI(aURI)
@ -166,7 +167,7 @@ ScriptLoadRequest::SetTextSource()
{
MOZ_ASSERT(IsUnknownDataType());
mDataType = DataType::eTextSource;
mScriptData.emplace(VariantType<Vector<char16_t>>());
mScriptData.emplace(VariantType<ScriptTextBuffer>());
}
void
@ -175,7 +176,7 @@ ScriptLoadRequest::SetBinASTSource()
#ifdef JS_BUILD_BINAST
MOZ_ASSERT(IsUnknownDataType());
mDataType = DataType::eBinASTSource;
mScriptData.emplace(VariantType<Vector<uint8_t>>());
mScriptData.emplace(VariantType<BinASTSourceBuffer>());
#else
MOZ_CRASH("BinAST not supported");
#endif

Просмотреть файл

@ -171,21 +171,28 @@ public:
void SetBinASTSource();
void SetBytecode();
const Vector<char16_t>& ScriptText() const {
using ScriptTextBuffer = Vector<char16_t, 0, JSMallocAllocPolicy>;
using BinASTSourceBuffer = Vector<uint8_t>;
const ScriptTextBuffer& ScriptText() const
{
MOZ_ASSERT(IsTextSource());
return mScriptData->as<Vector<char16_t>>();
return mScriptData->as<ScriptTextBuffer>();
}
Vector<char16_t>& ScriptText() {
ScriptTextBuffer& ScriptText()
{
MOZ_ASSERT(IsTextSource());
return mScriptData->as<Vector<char16_t>>();
return mScriptData->as<ScriptTextBuffer>();
}
const Vector<uint8_t>& ScriptBinASTData() const {
const BinASTSourceBuffer& ScriptBinASTData() const
{
MOZ_ASSERT(IsBinASTSource());
return mScriptData->as<Vector<uint8_t>>();
return mScriptData->as<BinASTSourceBuffer>();
}
Vector<uint8_t>& ScriptBinASTData() {
BinASTSourceBuffer& ScriptBinASTData()
{
MOZ_ASSERT(IsBinASTSource());
return mScriptData->as<Vector<uint8_t>>();
return mScriptData->as<BinASTSourceBuffer>();
}
enum class ScriptMode : uint8_t {
@ -252,7 +259,11 @@ public:
// Holds script source data for non-inline scripts. Don't use nsString so we
// can give ownership to jsapi. Holds either char16_t source text characters
// or BinAST encoded bytes depending on mSourceEncoding.
Maybe<Variant<Vector<char16_t>, Vector<uint8_t>>> mScriptData;
Maybe<Variant<ScriptTextBuffer, BinASTSourceBuffer>> mScriptData;
// The length of script source text, set when reading completes. This is used
// since mScriptData is cleared when the source is passed to the JS engine.
size_t mScriptTextLength;
// Holds the SRI serialized hash and the script bytecode for non-inline
// scripts.

Просмотреть файл

@ -1907,14 +1907,13 @@ SourceBufferHolder
ScriptLoader::GetScriptSource(JSContext* aCx, ScriptLoadRequest* aRequest)
{
// Return a SourceBufferHolder object holding the script's source text.
// Ownership of the buffer is transferred to the resulting SourceBufferHolder.
// If there's no script text, we try to get it from the element
if (aRequest->mIsInline) {
nsAutoString inlineData;
aRequest->mElement->GetScriptText(inlineData);
// Copy string to JS allocated buffer and transfer ownership to
// SourceBufferHolder result.
size_t nbytes = inlineData.Length() * sizeof(char16_t);
JS::UniqueTwoByteChars chars(static_cast<char16_t*>(JS_malloc(aCx, nbytes)));
MOZ_RELEASE_ASSERT(chars);
@ -1922,9 +1921,10 @@ ScriptLoader::GetScriptSource(JSContext* aCx, ScriptLoadRequest* aRequest)
return SourceBufferHolder(std::move(chars), inlineData.Length());
}
return SourceBufferHolder(aRequest->ScriptText().begin(),
aRequest->ScriptText().length(),
SourceBufferHolder::NoOwnership);
size_t length = aRequest->ScriptText().length();
return SourceBufferHolder(aRequest->ScriptText().extractOrCopyRawBuffer(),
length,
SourceBufferHolder::GiveOwnership);
}
nsresult
@ -2197,7 +2197,7 @@ ScriptLoader::ShouldCacheBytecode(ScriptLoadRequest* aRequest)
size_t sourceLength;
size_t minLength;
if (aRequest->IsTextSource()) {
sourceLength = aRequest->ScriptText().length();
sourceLength = aRequest->mScriptTextLength;
minLength = sourceLengthMin;
} else {
MOZ_ASSERT(aRequest->IsBinASTSource());