Bug 1359653: Part 1 - Use a const Range rather than a Vector for XDR decoding. r=shu

MozReview-Commit-ID: JkGNmOAKAxD

--HG--
extra : source : 473e6a1ef169a9ac556486680306b9c286774b74
This commit is contained in:
Kris Maglione 2017-05-05 15:47:10 -07:00
Родитель 5f874863a8
Коммит 81232b555a
5 изменённых файлов: 127 добавлений и 54 удалений

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

@ -4209,8 +4209,18 @@ JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
OffThreadCompileCallback callback, void* callbackData)
{
MOZ_ASSERT(CanCompileOffThread(cx, options, buffer.length() - cursor));
return StartOffThreadDecodeScript(cx, options, buffer, cursor, callback, callbackData);
JS::TranscodeRange range(buffer.begin() + cursor, buffer.length() - cursor);
MOZ_ASSERT(CanCompileOffThread(cx, options, range.length()));
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
}
JS_PUBLIC_API(bool)
JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
OffThreadCompileCallback callback, void* callbackData)
{
MOZ_ASSERT(CanCompileOffThread(cx, options, range.length()));
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
}
JS_PUBLIC_API(JSScript*)
@ -7030,6 +7040,15 @@ JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript
return decoder.resultCode();
}
JS_PUBLIC_API(JS::TranscodeResult)
JS::DecodeScript(JSContext* cx, const TranscodeRange& range, JS::MutableHandleScript scriptp)
{
XDRDecoder decoder(cx, range);
decoder.codeScript(scriptp);
MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
return decoder.resultCode();
}
JS_PUBLIC_API(JS::TranscodeResult)
JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer,
JS::MutableHandleFunction funp,

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

@ -4278,6 +4278,11 @@ DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
OffThreadCompileCallback callback, void* callbackData);
extern JS_PUBLIC_API(bool)
DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
OffThreadCompileCallback callback, void* callbackData);
extern JS_PUBLIC_API(JSScript*)
FinishOffThreadScriptDecoder(JSContext* cx, void* token);
@ -6159,6 +6164,7 @@ class MOZ_RAII AutoHideScriptedCaller
*/
typedef mozilla::Vector<uint8_t> TranscodeBuffer;
typedef mozilla::Range<uint8_t> TranscodeRange;
enum TranscodeResult
{
@ -6188,6 +6194,9 @@ extern JS_PUBLIC_API(TranscodeResult)
DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
size_t cursorIndex = 0);
extern JS_PUBLIC_API(TranscodeResult)
DecodeScript(JSContext* cx, const TranscodeRange& range, JS::MutableHandleScript scriptp);
extern JS_PUBLIC_API(TranscodeResult)
DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleFunction funp,
size_t cursorIndex = 0);

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

@ -300,25 +300,27 @@ static const JSClass parseTaskGlobalClass = {
ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
const char16_t* chars, size_t length,
JS::OffThreadCompileCallback callback, void* callbackData)
: kind(kind), options(cx), chars(chars), length(length),
: kind(kind), options(cx),
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
parseGlobal(parseGlobal),
callback(callback), callbackData(callbackData),
script(nullptr), sourceObject(nullptr),
overRecursed(false), outOfMemory(false)
{
data.construct<TwoByteChars>(chars, length);
}
ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData)
: kind(kind), options(cx), buffer(&buffer), cursor(cursor),
: kind(kind), options(cx),
alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
parseGlobal(parseGlobal),
callback(callback), callbackData(callbackData),
script(nullptr), sourceObject(nullptr),
overRecursed(false), outOfMemory(false)
{
data.construct<const JS::TranscodeRange>(range);
}
bool
@ -385,7 +387,8 @@ ScriptParseTask::ScriptParseTask(JSContext* cx, JSObject* parseGlobal,
void
ScriptParseTask::parse(JSContext* cx)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
auto& range = data.ref<TwoByteChars>();
SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership);
script = frontend::CompileGlobalScript(cx, alloc, ScopeKind::Global,
options, srcBuf,
/* sourceObjectOut = */ &sourceObject);
@ -402,17 +405,18 @@ ModuleParseTask::ModuleParseTask(JSContext* cx, JSObject* parseGlobal,
void
ModuleParseTask::parse(JSContext* cx)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
auto& range = data.ref<TwoByteChars>();
SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership);
ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject);
if (module)
script = module->script();
}
ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, JSObject* parseGlobal,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData)
: ParseTask(ParseTaskKind::ScriptDecode, cx, parseGlobal,
buffer, cursor, callback, callbackData)
range, callback, callbackData)
{
}
@ -421,7 +425,7 @@ ScriptDecodeTask::parse(JSContext* cx)
{
RootedScript resultScript(cx);
XDROffThreadDecoder decoder(cx, alloc, &options, /* sourceObjectOut = */ &sourceObject,
*buffer, cursor);
data.ref<const JS::TranscodeRange>());
decoder.codeScript(&resultScript);
MOZ_ASSERT(bool(resultScript) == (decoder.resultCode() == JS::TranscodeResult_Ok));
if (decoder.resultCode() == JS::TranscodeResult_Ok) {
@ -653,12 +657,11 @@ js::StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& optio
bool
js::StartOffThreadDecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData)
{
auto functor = [&](JSObject* global) -> ScriptDecodeTask* {
return cx->new_<ScriptDecodeTask>(cx, global, buffer, cursor,
callback, callbackData);
return cx->new_<ScriptDecodeTask>(cx, global, range, callback, callbackData);
};
return StartOffThreadParseTask(cx, options, ParseTaskKind::ScriptDecode, functor);
}

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

@ -15,6 +15,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/MaybeOneOf.h"
#include "mozilla/PodOperations.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Variant.h"
@ -534,7 +535,7 @@ StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& options,
bool
StartOffThreadDecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData);
/*
@ -593,21 +594,9 @@ struct ParseTask
{
ParseTaskKind kind;
OwningCompileOptions options;
// Anonymous union, the only correct interpretation is provided by the
// ParseTaskKind value, or from the virtual parse function.
union {
struct {
const char16_t* chars;
size_t length;
};
struct {
// This should be a reference, but C++ prevents us from using union
// with references as it assumes the reference constness might be
// violated.
JS::TranscodeBuffer* const buffer;
size_t cursor;
};
};
mozilla::MaybeOneOf<const JS::TranscodeRange, JS::TwoByteChars> data;
LifoAlloc alloc;
// Rooted pointer to the global object to use while parsing.
@ -635,7 +624,7 @@ struct ParseTask
const char16_t* chars, size_t length,
JS::OffThreadCompileCallback callback, void* callbackData);
ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData);
bool init(JSContext* cx, const ReadOnlyCompileOptions& options);
@ -671,7 +660,7 @@ struct ModuleParseTask : public ParseTask
struct ScriptDecodeTask : public ParseTask
{
ScriptDecodeTask(JSContext* cx, JSObject* parseGlobal,
JS::TranscodeBuffer& buffer, size_t cursor,
const JS::TranscodeRange& range,
JS::OffThreadCompileCallback callback, void* callbackData);
void parse(JSContext* cx) override;
};

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

@ -15,30 +15,35 @@
namespace js {
class XDRBuffer {
class XDRBufferBase
{
public:
XDRBuffer(JSContext* cx, JS::TranscodeBuffer& buffer, size_t cursor = 0)
: context_(cx), buffer_(buffer), cursor_(cursor) { }
explicit XDRBufferBase(JSContext* cx, size_t cursor = 0)
: context_(cx), cursor_(cursor) { }
JSContext* cx() const {
return context_;
}
const uint8_t* read(size_t n) {
MOZ_ASSERT(cursor_ < buffer_.length());
uint8_t* ptr = &buffer_[cursor_];
cursor_ += n;
return ptr;
size_t cursor() const {
return cursor_;
}
const char* readCString() {
char* ptr = reinterpret_cast<char*>(&buffer_[cursor_]);
uint8_t* end = reinterpret_cast<uint8_t*>(strchr(ptr, '\0')) + 1;
MOZ_ASSERT(buffer_.begin() < end);
MOZ_ASSERT(end <= buffer_.end());
cursor_ = end - buffer_.begin();
return ptr;
}
protected:
JSContext* const context_;
size_t cursor_;
};
template <XDRMode mode>
class XDRBuffer;
template <>
class XDRBuffer<XDR_ENCODE> : public XDRBufferBase
{
public:
XDRBuffer(JSContext* cx, JS::TranscodeBuffer& buffer, size_t cursor = 0)
: XDRBufferBase(cx, cursor),
buffer_(buffer) { }
uint8_t* write(size_t n) {
MOZ_ASSERT(n != 0);
@ -51,14 +56,55 @@ class XDRBuffer {
return ptr;
}
size_t cursor() const {
return cursor_;
const char* readCString() {
MOZ_CRASH("Should never read in encode mode");
return nullptr;
}
const uint8_t* read(size_t n) {
MOZ_CRASH("Should never read in encode mode");
return nullptr;
}
private:
JSContext* const context_;
JS::TranscodeBuffer& buffer_;
size_t cursor_;
};
template <>
class XDRBuffer<XDR_DECODE> : public XDRBufferBase
{
public:
XDRBuffer(JSContext* cx, const JS::TranscodeRange& range)
: XDRBufferBase(cx),
buffer_(range) { }
XDRBuffer(JSContext* cx, JS::TranscodeBuffer& buffer, size_t cursor = 0)
: XDRBufferBase(cx, cursor),
buffer_(buffer.begin(), buffer.length()) { }
const char* readCString() {
char* ptr = reinterpret_cast<char*>(&buffer_[cursor_]);
uint8_t* end = reinterpret_cast<uint8_t*>(strchr(ptr, '\0')) + 1;
MOZ_ASSERT(buffer_.begin().get() < end);
MOZ_ASSERT(end <= buffer_.end().get());
cursor_ = end - buffer_.begin().get();
return ptr;
}
const uint8_t* read(size_t n) {
MOZ_ASSERT(cursor_ < buffer_.length());
uint8_t* ptr = &buffer_[cursor_];
cursor_ += n;
return ptr;
}
uint8_t* write(size_t n) {
MOZ_CRASH("Should never write in decode mode");
return nullptr;
}
private:
const JS::TranscodeRange buffer_;
};
class XDRCoderBase;
@ -124,7 +170,7 @@ template <XDRMode mode>
class XDRState : public XDRCoderBase
{
public:
XDRBuffer buf;
XDRBuffer<mode> buf;
private:
JS::TranscodeResult resultCode_;
@ -135,6 +181,13 @@ class XDRState : public XDRCoderBase
{
}
template <typename RangeType>
XDRState(JSContext* cx, const RangeType& range)
: buf(cx, range),
resultCode_(JS::TranscodeResult_Ok)
{
}
virtual ~XDRState() {};
JSContext* cx() const {
@ -307,8 +360,8 @@ class XDROffThreadDecoder : public XDRDecoder
XDROffThreadDecoder(JSContext* cx, LifoAlloc& alloc,
const ReadOnlyCompileOptions* options,
ScriptSourceObject** sourceObjectOut,
JS::TranscodeBuffer& buffer, size_t cursor = 0)
: XDRDecoder(cx, buffer, cursor),
const JS::TranscodeRange& range)
: XDRDecoder(cx, range),
options_(options),
sourceObjectOut_(sourceObjectOut),
alloc_(alloc)