Skip to content

Commit

Permalink
Bug 1838771 - Assert the thread matches between JS::SetNativeStackQuo…
Browse files Browse the repository at this point in the history
…ta call and JS::CompileGlobalScriptToStencil for JS::FrontendContext. r=nbp

Differential Revision: https://phabricator.services.mozilla.com/D181201
  • Loading branch information
arai-a committed Jun 28, 2023
1 parent 446a595 commit c1cdda9
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 0 deletions.
2 changes: 2 additions & 0 deletions config/check_spidermonkey_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@
"gc/StatsPhasesGenerated.inc", # Included in the body of gc/Statistics.cpp
"psapi.h", # Must be included after "util/WindowsWrapper.h" on Windows
"machine/endian.h", # Must be included after <sys/types.h> on BSD
"process.h", # Windows-specific
"winbase.h", # Must precede other system headers(?)
"windef.h", # Must precede other system headers(?)
"windows.h", # Must precede other system headers(?)
]
)

Expand Down
5 changes: 5 additions & 0 deletions js/public/experimental/CompileScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ JS_PUBLIC_API JS::FrontendContext* NewFrontendContext();
// Destroy a front-end context allocated with NewFrontendContext.
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::NativeStackSize stackSize);

Expand Down
12 changes: 12 additions & 0 deletions js/src/frontend/CompileScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,26 +154,38 @@ already_AddRefed<JS::Stencil> JS::CompileGlobalScriptToStencil(
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
JS::CompilationStorage& compileStorage) {
#ifdef DEBUG
fc->assertNativeStackLimitThread();
#endif
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
}

already_AddRefed<JS::Stencil> JS::CompileGlobalScriptToStencil(
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
#ifdef DEBUG
fc->assertNativeStackLimitThread();
#endif
return CompileGlobalScriptToStencilImpl(fc, options, srcBuf, compileStorage);
}

already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
JS::SourceText<mozilla::Utf8Unit>& srcBuf,
JS::CompilationStorage& compileStorage) {
#ifdef DEBUG
fc->assertNativeStackLimitThread();
#endif
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
compileStorage);
}

already_AddRefed<JS::Stencil> JS::CompileModuleScriptToStencil(
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput,
JS::SourceText<char16_t>& srcBuf, JS::CompilationStorage& compileStorage) {
#ifdef DEBUG
fc->assertNativeStackLimitThread();
#endif
return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf,
compileStorage);
}
Expand Down
37 changes: 37 additions & 0 deletions js/src/frontend/FrontendContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

#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 "js/AllocPolicy.h" // js::ReportOutOfMemory
#include "js/friend/StackLimits.h" // js::ReportOverRecursed
Expand Down Expand Up @@ -61,6 +68,10 @@ void FrontendContext::setStackQuota(JS::NativeStackSize stackSize) {
stackLimit_ = JS::GetNativeStackLimit(GetNativeStackBase(), stackSize - 1);
}
#endif // !__wasi__

#ifdef DEBUG
setNativeStackLimitThread();
#endif
}

bool FrontendContext::allocateOwnedPool() {
Expand Down Expand Up @@ -164,6 +175,10 @@ void FrontendContext::setCurrentJSContext(JSContext* cx) {
nameCollectionPool_ = &cx->frontendCollectionPool();
scriptDataTableHolder_ = &cx->runtime()->scriptDataTableHolder();
stackLimit_ = cx->stackLimitForCurrentPrincipal();

#ifdef DEBUG
setNativeStackLimitThread();
#endif
}

void FrontendContext::convertToRuntimeError(
Expand Down Expand Up @@ -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__
void FrontendContext::incWasiRecursionDepth() {
if (maybeCx_) {
Expand Down
19 changes: 19 additions & 0 deletions js/src/frontend/FrontendContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,22 @@ class FrontendContext {

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;

#ifdef DEBUG
// The thread ID where the native stack limit is set.
mozilla::Maybe<size_t> stackLimitThreadId_;
#endif

protected:
// (optional) Current JSContext to support main-thread-specific
// handling for error reporting, GC, and memory allocation.
Expand Down Expand Up @@ -177,6 +191,11 @@ class FrontendContext {
bool checkWasiRecursionLimit();
#endif // __wasi__

#ifdef DEBUG
void setNativeStackLimitThread();
void assertNativeStackLimitThread();
#endif

private:
void ReportOutOfMemory();
void addPendingOutOfMemory();
Expand Down

0 comments on commit c1cdda9

Please sign in to comment.