diff --git a/include/v8.h b/include/v8.h index be61790912..c3d9b4af5c 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1945,6 +1945,11 @@ struct SampleInfo { // executing an external callback. }; +struct MemoryRange { + const void* start; + size_t length_in_bytes; +}; + /** * A JSON Parser and Stringifier. */ @@ -8156,7 +8161,9 @@ class V8_EXPORT Isolate { void SetStackLimit(uintptr_t stack_limit); /** - * Returns a memory range that can potentially contain jitted code. + * Returns a memory range that can potentially contain jitted code. Code for + * V8's 'builtins' will not be in this range if embedded builtins is enabled. + * Instead, see GetBuiltinsCodeRange. * * On Win64, embedders are advised to install function table callbacks for * these ranges, as default SEH won't be able to unwind through jitted code. @@ -8170,6 +8177,15 @@ class V8_EXPORT Isolate { */ void GetCodeRange(void** start, size_t* length_in_bytes); + /** + * Returns a memory range containing the code for V8's builtin functions + * which are shared across isolates. + * + * If embedded builtins are disabled, then the memory range will be a null + * pointer with 0 length. + */ + MemoryRange GetBuiltinsCodeRange(); + /** Set the callback to invoke in case of fatal errors. */ void SetFatalErrorHandler(FatalErrorCallback that); diff --git a/src/api.cc b/src/api.cc index d141496c57..0be54ac9ea 100644 --- a/src/api.cc +++ b/src/api.cc @@ -8709,6 +8709,11 @@ void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) { } } +MemoryRange Isolate::GetBuiltinsCodeRange() { + i::Isolate* isolate = reinterpret_cast(this); + return {reinterpret_cast(isolate->embedded_blob()), + isolate->embedded_blob_size()}; +} #define CALLBACK_SETTER(ExternalName, Type, InternalName) \ void Isolate::Set##ExternalName(Type callback) { \ diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 265d766381..b6d19e5210 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -28761,3 +28761,29 @@ TEST(TestSetWasmThreadsEnabledCallback) { i::FLAG_experimental_wasm_threads = false; CHECK(i_isolate->AreWasmThreadsEnabled(i_context)); } + +TEST(TestGetBuiltinsCodeRange) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + i::Isolate* i_isolate = reinterpret_cast(isolate); + + v8::MemoryRange builtins_range = isolate->GetBuiltinsCodeRange(); + + // Check that each off-heap builtin is within the builtins code range. + if (i::FLAG_embedded_builtins) { + for (int id = 0; id < i::Builtins::builtin_count; id++) { + if (!i::Builtins::IsIsolateIndependent(id)) continue; + i::Code* builtin = i_isolate->builtins()->builtin(id); + i::Address start = builtin->InstructionStart(); + i::Address end = start + builtin->InstructionSize(); + + i::Address builtins_start = + reinterpret_cast(builtins_range.start); + CHECK(start >= builtins_start && + end < builtins_start + builtins_range.length_in_bytes); + } + } else { + CHECK_EQ(nullptr, builtins_range.start); + CHECK_EQ(0, builtins_range.length_in_bytes); + } +}