зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5f874863a8
Коммит
81232b555a
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче