Bug 1773324 - Intro OffThreadErrorContext for off-thread compilation r=arai

DummyTokenStreams created when handling RegEx should be happening at JS
runtime, so on main thread (unless maybe workers?); so GeneralErrorContext is
appropriate there.

Differential Revision: https://phabricator.services.mozilla.com/D150644
This commit is contained in:
Bryan Thrall 2022-07-25 18:57:31 +00:00
Родитель 7e781e6879
Коммит 442eab3d26
10 изменённых файлов: 62 добавлений и 31 удалений

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

@ -342,8 +342,9 @@ bool js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res,
static bool CheckPatternSyntaxSlow(JSContext* cx, Handle<JSAtom*> pattern,
RegExpFlags flags) {
LifoAllocScope allocScope(&cx->tempLifoAlloc());
GeneralErrorContext ec(cx);
CompileOptions options(cx);
frontend::DummyTokenStream dummyTokenStream(cx, options);
frontend::DummyTokenStream dummyTokenStream(cx, &ec, options);
return irregexp::CheckPatternSyntax(cx, dummyTokenStream, pattern, flags);
}

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

@ -277,6 +277,7 @@ bool ConvertRegExpData(JSContext* cx, const SmooshResult& result,
return false;
}
GeneralErrorContext ec(cx);
for (size_t i = 0; i < len; i++) {
SmooshRegExpItem& item = result.regexps.data[i];
auto s = smoosh_get_slice_at(result, item.pattern);
@ -314,7 +315,7 @@ bool ConvertRegExpData(JSContext* cx, const SmooshResult& result,
mozilla::Range<const char16_t> range(pattern.get(), length);
TokenStreamAnyChars ts(cx, compilationState.input.options,
TokenStreamAnyChars ts(cx, &ec, compilationState.input.options,
/* smg = */ nullptr);
// See Parser<FullParseHandler, Unit>::newRegExp.

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

@ -162,7 +162,7 @@ ParserBase::ParserBase(JSContext* cx, ErrorContext* ec,
const ReadOnlyCompileOptions& options,
bool foldConstants, CompilationState& compilationState)
: ParserSharedBase(cx, compilationState, ParserSharedBase::Kind::Parser),
anyChars(cx, options, this),
anyChars(cx, ec, options, this),
ss(nullptr),
foldConstants_(foldConstants),
ec_(ec),

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

@ -490,11 +490,11 @@ SourceCoords::LineToken SourceCoords::lineToken(uint32_t offset) const {
return LineToken(indexFromOffset(offset), offset);
}
TokenStreamAnyChars::TokenStreamAnyChars(JSContext* cx,
TokenStreamAnyChars::TokenStreamAnyChars(JSContext* cx, ErrorContext* ec,
const ReadOnlyCompileOptions& options,
StrictModeGetter* smg)
: cx(cx),
ec(cx),
ec(ec),
options_(options),
strictModeGetter_(smg),
filename_(options.filename()),
@ -610,7 +610,7 @@ void TokenStreamAnyChars::reportErrorNoOffsetVA(unsigned errorNumber,
ErrorMetadata metadata;
computeErrorMetadataNoOffset(&metadata);
ReportCompileErrorLatin1(&ec, cx, std::move(metadata), nullptr, errorNumber,
ReportCompileErrorLatin1(ec, cx, std::move(metadata), nullptr, errorNumber,
args);
}
@ -1041,7 +1041,7 @@ MOZ_COLD void TokenStreamChars<Utf8Unit, AnyCharsAccess>::internalEncodingError(
break;
}
ReportCompileErrorLatin1(&anyChars.ec, anyChars.cx, std::move(err),
ReportCompileErrorLatin1(anyChars.ec, anyChars.cx, std::move(err),
std::move(notes), errorNumber, &args);
} while (false);

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

@ -562,7 +562,7 @@ class TokenStreamAnyChars : public TokenStreamShared {
JSContext* const cx;
mutable GeneralErrorContext ec;
ErrorContext* const ec;
/** Options used for parsing/tokenizing. */
const JS::ReadOnlyCompileOptions& options_;
@ -721,7 +721,8 @@ class TokenStreamAnyChars : public TokenStreamShared {
// End of fields.
public:
TokenStreamAnyChars(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
TokenStreamAnyChars(JSContext* cx, ErrorContext* ec,
const JS::ReadOnlyCompileOptions& options,
StrictModeGetter* smg);
template <typename Unit, class AnyCharsAccess>
@ -874,7 +875,7 @@ class TokenStreamAnyChars : public TokenStreamShared {
char16_t* sourceMapURL() { return sourceMapURL_.get(); }
ErrorContext* context() const { return &ec; }
ErrorContext* context() const { return ec; }
JSContext* allocator() const { return cx; }
using LineToken = SourceCoords::LineToken;
@ -2550,7 +2551,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
private:
// Implement ErrorReportMixin.
ErrorContext* getContext() const override { return &anyCharsAccess().ec; }
ErrorContext* getContext() const override { return anyCharsAccess().ec; }
JSAllocator* getAllocator() const override { return anyCharsAccess().cx; }
@ -2931,18 +2932,19 @@ class MOZ_STACK_CLASS TokenStream
using Unit = char16_t;
public:
TokenStream(JSContext* cx, ParserAtomsTable* parserAtoms,
TokenStream(JSContext* cx, ErrorContext* ec, ParserAtomsTable* parserAtoms,
const JS::ReadOnlyCompileOptions& options, const Unit* units,
size_t length, StrictModeGetter* smg)
: TokenStreamAnyChars(cx, options, smg),
: TokenStreamAnyChars(cx, ec, options, smg),
TokenStreamSpecific<Unit, TokenStreamAnyCharsAccess>(
cx, parserAtoms, options, units, length) {}
};
class MOZ_STACK_CLASS DummyTokenStream final : public TokenStream {
public:
DummyTokenStream(JSContext* cx, const JS::ReadOnlyCompileOptions& options)
: TokenStream(cx, nullptr, options, nullptr, 0, nullptr) {}
DummyTokenStream(JSContext* cx, ErrorContext* ec,
const JS::ReadOnlyCompileOptions& options)
: TokenStream(cx, ec, nullptr, options, nullptr, 0, nullptr) {}
};
template <class TokenStreamSpecific>

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

@ -598,8 +598,9 @@ bool CompilePattern(JSContext* cx, MutableHandleRegExpShared re,
FlatStringReader patternBytes(cx, pattern);
if (!RegExpParser::ParseRegExp(cx->isolate, &zone, &patternBytes, flags,
&data)) {
GeneralErrorContext ec(cx);
JS::CompileOptions options(cx);
DummyTokenStream dummyTokenStream(cx, options);
DummyTokenStream dummyTokenStream(cx, &ec, options);
ReportSyntaxError(dummyTokenStream, data, pattern);
return false;
}

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

@ -29,26 +29,17 @@ using JS::UniqueTwoByteChars;
GeneralErrorContext::GeneralErrorContext(JSContext* cx) : cx_(cx) {}
bool GeneralErrorContext::addPendingError(CompileError** error) {
if (cx_->isHelperThreadContext()) {
return cx_->addPendingCompileError(error);
}
return true;
}
bool GeneralErrorContext::addPendingError(CompileError** error) { return true; }
void GeneralErrorContext::reportError(CompileError* err) {
// On the main thread, report the error immediately. When compiling off
// thread, save the error so that the thread finishing the parse can report
// it later.
// On the main thread, report the error immediately.
if (MOZ_UNLIKELY(!cx_->runtime()->hasInitializedSelfHosting())) {
selfHosting_ErrorReporter(err);
return;
}
if (!cx_->isHelperThreadContext()) {
err->throwError(cx_);
}
err->throwError(cx_);
}
void GeneralErrorContext::reportWarning(CompileError* err) {
@ -57,6 +48,26 @@ void GeneralErrorContext::reportWarning(CompileError* err) {
}
}
OffThreadErrorContext::OffThreadErrorContext(JSContext* cx) : cx_(cx) {}
bool OffThreadErrorContext::addPendingError(CompileError** error) {
// When compiling off thread, save the error so that the thread finishing the
// parse can report it later.
return cx_->addPendingCompileError(error);
}
void OffThreadErrorContext::reportError(CompileError* err) {
if (MOZ_UNLIKELY(
!cx_->runtime()
->hasInitializedSelfHosting())) { // TODO can SelfHosting run on
// helper threads?
selfHosting_ErrorReporter(err);
return;
}
}
void OffThreadErrorContext::reportWarning(CompileError* err) {}
void js::CallWarningReporter(JSContext* cx, JSErrorReport* reportp) {
MOZ_ASSERT(reportp->isWarning());

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

@ -107,6 +107,19 @@ class GeneralErrorContext : public ErrorContext {
virtual void reportWarning(js::CompileError* err) override;
};
class OffThreadErrorContext : public ErrorContext {
private:
JSContext* cx_;
public:
explicit OffThreadErrorContext(JSContext* cx);
bool addPendingError(js::CompileError** error) override;
virtual void reportError(js::CompileError* err) override;
virtual void reportWarning(js::CompileError* err) override;
};
/**
* Report a compile error during script processing prior to execution of the
* script.

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

@ -722,7 +722,7 @@ void CompileToStencilTask<Unit>::parse(JSContext* cx) {
return;
}
GeneralErrorContext ec(cx); // TODO helper thread ErrorContext
OffThreadErrorContext ec(cx);
js::LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
stencil_ = frontend::CompileGlobalScriptToStencil(
cx, &ec, tempLifoAlloc, *stencilInput_, data, scopeKind);

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

@ -206,8 +206,9 @@ RegExpObject* RegExpObject::createSyntaxChecked(JSContext* cx,
RegExpObject* RegExpObject::create(JSContext* cx, Handle<JSAtom*> source,
RegExpFlags flags, NewObjectKind newKind) {
GeneralErrorContext ec(cx);
CompileOptions dummyOptions(cx);
frontend::DummyTokenStream dummyTokenStream(cx, dummyOptions);
frontend::DummyTokenStream dummyTokenStream(cx, &ec, dummyOptions);
LifoAllocScope allocScope(&cx->tempLifoAlloc());
if (!irregexp::CheckPatternSyntax(cx, dummyTokenStream, source, flags)) {
@ -1231,8 +1232,9 @@ JS_PUBLIC_API bool JS::CheckRegExpSyntax(JSContext* cx, const char16_t* chars,
AssertHeapIsIdle();
CHECK_THREAD(cx);
GeneralErrorContext ec(cx);
CompileOptions dummyOptions(cx);
frontend::DummyTokenStream dummyTokenStream(cx, dummyOptions);
frontend::DummyTokenStream dummyTokenStream(cx, &ec, dummyOptions);
LifoAllocScope allocScope(&cx->tempLifoAlloc());