Bug 1773324 - Replace ErrorReporting allocator with ErrorAllocator r=arai

ErrorAllocator is an adapter that allows MallocProvider to delegate
to polymorphic Contexts. MallocProvider provides a well-known interface,
but doesn't support polymorphism, so we resort to templating and adapters
like this.

JS::CharsToNewUTF8CharsZ() needs a definition in CharacterEncoding.cpp,
so for now I explicitly instantiate it for ErrorAllocator<JSContext>.
A better solution would be to move the definition to a header, but that's
a bigger task.

Differential Revision: https://phabricator.services.mozilla.com/D151179
This commit is contained in:
Bryan Thrall 2022-07-25 18:57:33 +00:00
parent 29bcf1e310
commit 43ad49bda4
4 changed files with 82 additions and 17 deletions

View File

@ -235,8 +235,8 @@ inline Latin1CharsZ LossyTwoByteCharsToNewLatin1CharsZ(JSContext* cx,
return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
}
template <typename CharT>
extern UTF8CharsZ CharsToNewUTF8CharsZ(JSContext* cx,
template <typename CharT, typename Allocator>
extern UTF8CharsZ CharsToNewUTF8CharsZ(Allocator* alloc,
const mozilla::Range<CharT> chars);
JS_PUBLIC_API uint32_t Utf8ToOneUcs4Char(const uint8_t* utf8Buffer,

View File

@ -19,6 +19,7 @@
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
#include "util/StringBuffer.h"
#include "util/Unicode.h" // unicode::REPLACEMENT_CHARACTER
#include "vm/ErrorContext.h"
#include "vm/JSContext.h"
using mozilla::AsChars;
@ -133,15 +134,15 @@ void ConvertToUTF8<const Latin1Char>(mozilla::Span<const Latin1Char> src,
(void)ConvertLatin1toUtf8Partial(AsChars(src), dst);
}
template <typename CharT>
UTF8CharsZ JS::CharsToNewUTF8CharsZ(JSContext* cx,
template <typename CharT, typename Allocator>
UTF8CharsZ JS::CharsToNewUTF8CharsZ(Allocator* alloc,
const mozilla::Range<CharT> chars) {
/* Get required buffer size. */
const CharT* str = chars.begin().get();
size_t len = ::GetDeflatedUTF8StringLength(str, chars.length());
/* Allocate buffer. */
char* utf8 = cx->pod_malloc<char>(len + 1);
char* utf8 = alloc->template pod_malloc<char>(len + 1);
if (!utf8) {
return UTF8CharsZ();
}
@ -165,6 +166,19 @@ template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
JSContext* cx, const mozilla::Range<const char16_t> chars);
template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
ErrorAllocator<JSContext>* cx, const mozilla::Range<Latin1Char> chars);
template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
ErrorAllocator<JSContext>* cx, const mozilla::Range<char16_t> chars);
template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
ErrorAllocator<JSContext>* cx,
const mozilla::Range<const Latin1Char> chars);
template UTF8CharsZ JS::CharsToNewUTF8CharsZ(
ErrorAllocator<JSContext>* cx, const mozilla::Range<const char16_t> chars);
static const uint32_t INVALID_UTF8 = UINT32_MAX;
/*

View File

@ -8,6 +8,7 @@
#define vm_ErrorContext_h
#include "vm/ErrorReporting.h"
#include "vm/MallocProvider.h"
namespace js {
@ -24,6 +25,9 @@ class ErrorContext {
public:
virtual ~ErrorContext() = default;
virtual bool addPendingError(js::CompileError** error) = 0;
virtual void* onOutOfMemory(js::AllocFunction allocFunc, arena_id_t arena,
size_t nbytes, void* reallocPtr = nullptr) = 0;
virtual void reportAllocationOverflow() = 0;
virtual void reportError(js::CompileError* err) = 0;
virtual void reportWarning(js::CompileError* err) = 0;
@ -42,6 +46,10 @@ class GeneralErrorContext : public ErrorContext {
explicit GeneralErrorContext(JSContext* cx);
bool addPendingError(js::CompileError** error) override;
virtual void* onOutOfMemory(js::AllocFunction allocFunc, arena_id_t arena,
size_t nbytes,
void* reallocPtr = nullptr) override;
virtual void reportAllocationOverflow() override;
virtual void reportError(js::CompileError* err) override;
virtual void reportWarning(js::CompileError* err) override;
@ -61,6 +69,9 @@ class OffThreadErrorContext : public ErrorContext {
public:
OffThreadErrorContext() : alloc_(nullptr) {}
bool addPendingError(js::CompileError** error) override;
void* onOutOfMemory(js::AllocFunction allocFunc, arena_id_t arena,
size_t nbytes, void* reallocPtr = nullptr) override;
void reportAllocationOverflow() override;
virtual void reportError(js::CompileError* err) override;
virtual void reportWarning(js::CompileError* err) override;
@ -78,6 +89,21 @@ class OffThreadErrorContext : public ErrorContext {
}
};
template <typename Context>
class ErrorAllocator : public MallocProvider<ErrorAllocator<Context>> {
private:
Context* context_;
public:
explicit ErrorAllocator(Context* ec) : context_(ec) {}
void* onOutOfMemory(js::AllocFunction allocFunc, arena_id_t arena,
size_t nbytes, void* reallocPtr = nullptr) {
return context_->onOutOfMemory(allocFunc, arena, nbytes, reallocPtr);
}
void reportAllocationOverflow() { context_->reportAllocationOverflow(); }
};
} // namespace js
#endif /* vm_ErrorContext_h */

View File

@ -31,6 +31,15 @@ using JS::UniqueTwoByteChars;
GeneralErrorContext::GeneralErrorContext(JSContext* cx) : cx_(cx) {}
bool GeneralErrorContext::addPendingError(CompileError** error) { return true; }
void* GeneralErrorContext::onOutOfMemory(js::AllocFunction allocFunc,
arena_id_t arena, size_t nbytes,
void* reallocPtr) {
return cx_->onOutOfMemory(allocFunc, arena, nbytes, reallocPtr);
}
void GeneralErrorContext::reportAllocationOverflow() {
return cx_->reportAllocationOverflow();
}
void GeneralErrorContext::reportError(CompileError* err) {
// On the main thread, report the error immediately.
@ -76,6 +85,17 @@ bool OffThreadErrorContext::addPendingError(CompileError** error) {
*error = errors_.errors.back().get();
return true;
}
void* OffThreadErrorContext::onOutOfMemory(js::AllocFunction allocFunc,
arena_id_t arena, size_t nbytes,
void* reallocPtr) {
addPendingOutOfMemory();
return nullptr;
}
void OffThreadErrorContext::reportAllocationOverflow() {
// TODO Bug 1780599 - Currently allocation overflows are not reported for
// helper threads; see js::reportAllocationOverflow()
}
void OffThreadErrorContext::reportError(CompileError* err) {
// TODO Bug 1773324 - restore selfHosting_ErrorReporter if needed
@ -321,7 +341,8 @@ class MOZ_RAII AutoMessageArgs {
* if argsArg were strongly typed we'd still need casting below for this to
* compile, because typeArg is not known at compile-time here.
*/
bool init(JSAllocator* alloc, void* argsArg, uint16_t countArg,
template <typename Allocator>
bool init(Allocator* alloc, void* argsArg, uint16_t countArg,
ErrorArgumentsType typeArg, va_list ap) {
MOZ_ASSERT(countArg > 0);
@ -392,9 +413,9 @@ class MOZ_RAII AutoMessageArgs {
* that is not worth it here because AutoMessageArgs takes a void* anyway, and
* using void* here simplifies our callers a bit.
*/
template <typename T>
static bool ExpandErrorArgumentsHelper(JSContext* cx, JSErrorCallback callback,
void* userRef,
template <typename T, typename Allocator>
static bool ExpandErrorArgumentsHelper(JSContext* cx, Allocator* alloc,
JSErrorCallback callback, void* userRef,
const unsigned errorNumber,
void* messageArgs,
ErrorArgumentsType argumentsType,
@ -438,7 +459,7 @@ static bool ExpandErrorArgumentsHelper(JSContext* cx, JSErrorCallback callback,
size_t len = strlen(efs->format);
AutoMessageArgs args;
if (!args.init(cx, messageArgs, argCount, argumentsType, ap)) {
if (!args.init(alloc, messageArgs, argCount, argumentsType, ap)) {
return false;
}
@ -449,7 +470,7 @@ static bool ExpandErrorArgumentsHelper(JSContext* cx, JSErrorCallback callback,
* Note - the above calculation assumes that each argument
* is used once and only once in the expansion !!!
*/
char* utf8 = out = cx->pod_malloc<char>(expandedLength + 1);
char* utf8 = out = alloc->template pod_malloc<char>(expandedLength + 1);
if (!out) {
return false;
}
@ -493,7 +514,7 @@ static bool ExpandErrorArgumentsHelper(JSContext* cx, JSErrorCallback callback,
const char* defaultErrorMessage =
"No error message available for error number %d";
size_t nbytes = strlen(defaultErrorMessage) + 16;
char* message = cx->pod_malloc<char>(nbytes);
char* message = alloc->template pod_malloc<char>(nbytes);
if (!message) {
return false;
}
@ -509,7 +530,8 @@ bool js::ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap) {
MOZ_ASSERT(argumentsType == ArgumentsAreUnicode);
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber,
ErrorAllocator<JSContext> alloc(cx);
return ExpandErrorArgumentsHelper(cx, &alloc, callback, userRef, errorNumber,
messageArgs, argumentsType, reportp, ap);
}
@ -519,7 +541,8 @@ bool js::ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap) {
MOZ_ASSERT(argumentsType != ArgumentsAreUnicode);
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber,
ErrorAllocator<JSContext> alloc(cx);
return ExpandErrorArgumentsHelper(cx, &alloc, callback, userRef, errorNumber,
messageArgs, argumentsType, reportp, ap);
}
@ -527,8 +550,9 @@ bool js::ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap) {
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber, nullptr,
argumentsType, reportp, ap);
ErrorAllocator<JSContext> alloc(cx);
return ExpandErrorArgumentsHelper(cx, &alloc, callback, userRef, errorNumber,
nullptr, argumentsType, reportp, ap);
}
bool js::ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
@ -536,7 +560,8 @@ bool js::ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
const char16_t** messageArgs,
ErrorArgumentsType argumentsType,
JSErrorNotes::Note* notep, va_list ap) {
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber,
ErrorAllocator<JSContext> alloc(cx);
return ExpandErrorArgumentsHelper(cx, &alloc, callback, userRef, errorNumber,
messageArgs, argumentsType, notep, ap);
}