forked from mirrors/gecko-dev
Bug 1838771 - Assert the thread matches between JS::SetNativeStackQuota call and JS::CompileGlobalScriptToStencil for JS::FrontendContext. r=nbp
Differential Revision: https://phabricator.services.mozilla.com/D181201
This commit is contained in:
parent
446a595eeb
commit
c1cdda9cde
5 changed files with 75 additions and 0 deletions
|
|
@ -125,8 +125,10 @@ oddly_ordered_inclnames = set(
|
||||||
"gc/StatsPhasesGenerated.inc", # Included in the body of gc/Statistics.cpp
|
"gc/StatsPhasesGenerated.inc", # Included in the body of gc/Statistics.cpp
|
||||||
"psapi.h", # Must be included after "util/WindowsWrapper.h" on Windows
|
"psapi.h", # Must be included after "util/WindowsWrapper.h" on Windows
|
||||||
"machine/endian.h", # Must be included after <sys/types.h> on BSD
|
"machine/endian.h", # Must be included after <sys/types.h> on BSD
|
||||||
|
"process.h", # Windows-specific
|
||||||
"winbase.h", # Must precede other system headers(?)
|
"winbase.h", # Must precede other system headers(?)
|
||||||
"windef.h", # Must precede other system headers(?)
|
"windef.h", # Must precede other system headers(?)
|
||||||
|
"windows.h", # Must precede other system headers(?)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ JS_PUBLIC_API JS::FrontendContext* NewFrontendContext();
|
||||||
// Destroy a front-end context allocated with NewFrontendContext.
|
// Destroy a front-end context allocated with NewFrontendContext.
|
||||||
JS_PUBLIC_API void DestroyFrontendContext(JS::FrontendContext* fc);
|
JS_PUBLIC_API void DestroyFrontendContext(JS::FrontendContext* fc);
|
||||||
|
|
||||||
|
// Set the size of the native stack that should not be exceed. To disable
|
||||||
|
// stack size checking pass 0.
|
||||||
|
//
|
||||||
|
// WARNING: When the stack size checking is enabled, the JS::FrontendContext
|
||||||
|
// can be used only in the thread where JS::SetNativeStackQuota is called.
|
||||||
JS_PUBLIC_API void SetNativeStackQuota(JS::FrontendContext* fc,
|
JS_PUBLIC_API void SetNativeStackQuota(JS::FrontendContext* fc,
|
||||||
JS::NativeStackSize stackSize);
|
JS::NativeStackSize stackSize);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,12 +154,18 @@ already_AddRefed<JS::Stencil> JS::CompileGlobalScriptToStencil(
|
||||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||||
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
|
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
|
||||||
JS::CompilationStorage& compileStorage) {
|
JS::CompilationStorage& compileStorage) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fc->assertNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
|
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<JS::Stencil> JS::CompileGlobalScriptToStencil(
|
already_AddRefed<JS::Stencil> JS::CompileGlobalScriptToStencil(
|
||||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||||
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
|
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fc->assertNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
|
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,6 +173,9 @@ already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
|
||||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
|
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
|
||||||
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
|
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
|
||||||
JS::CompilationStorage& compileStorage) {
|
JS::CompilationStorage& compileStorage) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fc->assertNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
|
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
|
||||||
compileStorage);
|
compileStorage);
|
||||||
}
|
}
|
||||||
|
|
@ -174,6 +183,9 @@ already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
|
||||||
already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
|
already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
|
||||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
|
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
|
||||||
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
|
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fc->assertNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
|
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
|
||||||
compileStorage);
|
compileStorage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
#include "frontend/FrontendContext.h"
|
#include "frontend/FrontendContext.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
# include <process.h> // GetCurrentThreadId
|
||||||
|
#else
|
||||||
|
# include <pthread.h> // pthread_self
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "gc/GC.h"
|
#include "gc/GC.h"
|
||||||
#include "js/AllocPolicy.h" // js::ReportOutOfMemory
|
#include "js/AllocPolicy.h" // js::ReportOutOfMemory
|
||||||
#include "js/friend/StackLimits.h" // js::ReportOverRecursed
|
#include "js/friend/StackLimits.h" // js::ReportOverRecursed
|
||||||
|
|
@ -61,6 +68,10 @@ void FrontendContext::setStackQuota(JS::NativeStackSize stackSize) {
|
||||||
stackLimit_ = JS::GetNativeStackLimit(GetNativeStackBase(), stackSize - 1);
|
stackLimit_ = JS::GetNativeStackLimit(GetNativeStackBase(), stackSize - 1);
|
||||||
}
|
}
|
||||||
#endif // !__wasi__
|
#endif // !__wasi__
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
setNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendContext::allocateOwnedPool() {
|
bool FrontendContext::allocateOwnedPool() {
|
||||||
|
|
@ -164,6 +175,10 @@ void FrontendContext::setCurrentJSContext(JSContext* cx) {
|
||||||
nameCollectionPool_ = &cx->frontendCollectionPool();
|
nameCollectionPool_ = &cx->frontendCollectionPool();
|
||||||
scriptDataTableHolder_ = &cx->runtime()->scriptDataTableHolder();
|
scriptDataTableHolder_ = &cx->runtime()->scriptDataTableHolder();
|
||||||
stackLimit_ = cx->stackLimitForCurrentPrincipal();
|
stackLimit_ = cx->stackLimitForCurrentPrincipal();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
setNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendContext::convertToRuntimeError(
|
void FrontendContext::convertToRuntimeError(
|
||||||
|
|
@ -196,6 +211,28 @@ void FrontendContext::linkWithJSContext(JSContext* cx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static size_t GetTid() {
|
||||||
|
# if defined(_WIN32)
|
||||||
|
return size_t(GetCurrentThreadId());
|
||||||
|
# else
|
||||||
|
return size_t(pthread_self());
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendContext::setNativeStackLimitThread() {
|
||||||
|
stackLimitThreadId_.emplace(GetTid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendContext::assertNativeStackLimitThread() {
|
||||||
|
if (!stackLimitThreadId_.isSome()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(*stackLimitThreadId_ == GetTid());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __wasi__
|
#ifdef __wasi__
|
||||||
void FrontendContext::incWasiRecursionDepth() {
|
void FrontendContext::incWasiRecursionDepth() {
|
||||||
if (maybeCx_) {
|
if (maybeCx_) {
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,22 @@ class FrontendContext {
|
||||||
|
|
||||||
JS::ImportAssertionVector supportedImportAssertions_;
|
JS::ImportAssertionVector supportedImportAssertions_;
|
||||||
|
|
||||||
|
// Limit pointer for checking native stack consumption.
|
||||||
|
//
|
||||||
|
// The pointer is calculated based on the stack base of the current thread
|
||||||
|
// except for JS::NativeStackLimitMax. Once such value is set, this
|
||||||
|
// FrontendContext can be used only in the thread.
|
||||||
|
//
|
||||||
|
// In order to enforce this thread rule, setNativeStackLimitThread should
|
||||||
|
// be called when setting the value, and assertNativeStackLimitThread should
|
||||||
|
// be called at each entry-point that might make use of this field.
|
||||||
JS::NativeStackLimit stackLimit_ = JS::NativeStackLimitMax;
|
JS::NativeStackLimit stackLimit_ = JS::NativeStackLimitMax;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// The thread ID where the native stack limit is set.
|
||||||
|
mozilla::Maybe<size_t> stackLimitThreadId_;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// (optional) Current JSContext to support main-thread-specific
|
// (optional) Current JSContext to support main-thread-specific
|
||||||
// handling for error reporting, GC, and memory allocation.
|
// handling for error reporting, GC, and memory allocation.
|
||||||
|
|
@ -177,6 +191,11 @@ class FrontendContext {
|
||||||
bool checkWasiRecursionLimit();
|
bool checkWasiRecursionLimit();
|
||||||
#endif // __wasi__
|
#endif // __wasi__
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void setNativeStackLimitThread();
|
||||||
|
void assertNativeStackLimitThread();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReportOutOfMemory();
|
void ReportOutOfMemory();
|
||||||
void addPendingOutOfMemory();
|
void addPendingOutOfMemory();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue