perf: have ErrorThrower lazily lookup the current isolate (#46415)

perf: have ErrorThrower lazy-lookup the current isolate

ErrorThrower's default constructor is marked as "should rarely if ever
be used" because it's expensive to call.

Unfortunately, nearly every instance of ErrorThrower comes as an argument
in gin_helper's JS-->C++ function marshalling where a thrower is
default-constructed and then populated in gin_helper::GetNextArgument()
with an assignment operator to a temporary ErrorThrower constructed
with the gin::Arguments' isolate.

tldr: most of the time we use the slow constructor first, then throw
that work away unused by overwriting with a fast-constructed one.

This refactor avoids that cost by deferring the expensive work to
`ErrorThrower::isolate()`, where it happens only as a fallback iff
isolate_ hasn't been set.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
trop[bot] 2025-04-01 17:25:29 -05:00 committed by GitHub
parent 58b2c2e651
commit 01ce103ae1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 13 additions and 13 deletions

View file

@ -10,12 +10,11 @@
namespace gin_helper {
ErrorThrower::ErrorThrower(v8::Isolate* isolate) : isolate_(isolate) {}
// This constructor should be rarely if ever used, since
// v8::Isolate::GetCurrent() uses atomic loads and is thus a bit
// costly to invoke
ErrorThrower::ErrorThrower() : isolate_(v8::Isolate::GetCurrent()) {}
v8::Isolate* ErrorThrower::isolate() const {
// Callers should prefer to specify the isolate in the constructor,
// since GetCurrent() uses atomic loads and is thus a bit costly to invoke
return isolate_ ? isolate_.get() : v8::Isolate::GetCurrent();
}
void ErrorThrower::ThrowError(const std::string_view err_msg) const {
Throw(v8::Exception::Error, err_msg);
@ -39,9 +38,10 @@ void ErrorThrower::ThrowSyntaxError(const std::string_view err_msg) const {
void ErrorThrower::Throw(ErrorGenerator gen,
const std::string_view err_msg) const {
v8::Local<v8::Value> exception = gen(gin::StringToV8(isolate_, err_msg), {});
if (!isolate_->IsExecutionTerminating())
isolate_->ThrowException(exception);
v8::Isolate* isolate = this->isolate();
if (!isolate->IsExecutionTerminating())
isolate->ThrowException(gen(gin::StringToV8(isolate, err_msg), {}));
}
} // namespace gin_helper