deps: V8: cherry-pick efb1133eb894
Original commit message:
[api] Add v8::ScriptCompiler::CachedData::CompatibilityCheck()
This patch adds a new API v8::ScriptCompiler::CachedData::CompatibilityCheck()
in order to allow embedders to check if the code cache can be used in
the current isolate without looking up for the source code. It also returns more detailed reasons about why the code cache cannot be used
when it's bound to be rejected. This makes it possible to enforce
portability checks in case code code becomes CPU-dependent in the
future.
Refs: https://github.com/nodejs/node/issues/42566#issuecomment-1735862123
Change-Id: Ia1d677b949050add961af6fbf62c44342c061312
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4905290
Reviewed-by: Marja Hölttä <marja@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Cr-Commit-Position: refs/heads/main@{#90833}
Refs: efb1133eb8
PR-URL: https://github.com/nodejs/node/pull/51551
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
parent
ad0bcb9c02
commit
a3e0834ee4
@ -36,7 +36,7 @@
|
||||
|
||||
# Reset this number to 0 on major V8 upgrades.
|
||||
# Increment by one for each non-official patch applied to deps/v8.
|
||||
'v8_embedder_string': '-node.12',
|
||||
'v8_embedder_string': '-node.13',
|
||||
|
||||
##### V8 defaults for Node.js #####
|
||||
|
||||
|
21
deps/v8/include/v8-script.h
vendored
21
deps/v8/include/v8-script.h
vendored
@ -394,6 +394,27 @@ class V8_EXPORT ScriptCompiler {
|
||||
CachedData(const uint8_t* data, int length,
|
||||
BufferPolicy buffer_policy = BufferNotOwned);
|
||||
~CachedData();
|
||||
|
||||
enum CompatibilityCheckResult {
|
||||
// Don't change order/existing values of this enum since it keys into the
|
||||
// `code_cache_reject_reason` histogram. Append-only!
|
||||
kSuccess = 0,
|
||||
kMagicNumberMismatch = 1,
|
||||
kVersionMismatch = 2,
|
||||
kSourceMismatch = 3,
|
||||
kFlagsMismatch = 5,
|
||||
kChecksumMismatch = 6,
|
||||
kInvalidHeader = 7,
|
||||
kLengthMismatch = 8,
|
||||
kReadOnlySnapshotChecksumMismatch = 9,
|
||||
|
||||
// This should always point at the last real enum value.
|
||||
kLast = kReadOnlySnapshotChecksumMismatch
|
||||
};
|
||||
|
||||
// Check if the CachedData can be loaded in the given isolate.
|
||||
CompatibilityCheckResult CompatibilityCheck(Isolate* isolate);
|
||||
|
||||
// TODO(marja): Async compilation; add constructors which take a callback
|
||||
// which will be called when V8 no longer needs the data.
|
||||
const uint8_t* data;
|
||||
|
12
deps/v8/src/api/api.cc
vendored
12
deps/v8/src/api/api.cc
vendored
@ -1951,6 +1951,18 @@ ScriptCompiler::CachedData::~CachedData() {
|
||||
}
|
||||
}
|
||||
|
||||
ScriptCompiler::CachedData::CompatibilityCheckResult
|
||||
ScriptCompiler::CachedData::CompatibilityCheck(Isolate* isolate) {
|
||||
i::AlignedCachedData aligned(data, length);
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
i::SerializedCodeSanityCheckResult result;
|
||||
i::SerializedCodeData scd =
|
||||
i::SerializedCodeData::FromCachedDataWithoutSource(
|
||||
i_isolate->AsLocalIsolate(), &aligned, &result);
|
||||
return static_cast<ScriptCompiler::CachedData::CompatibilityCheckResult>(
|
||||
result);
|
||||
}
|
||||
|
||||
ScriptCompiler::StreamedSource::StreamedSource(
|
||||
std::unique_ptr<ExternalSourceStream> stream, Encoding encoding)
|
||||
: impl_(new i::ScriptStreamingData(std::move(stream), encoding)) {}
|
||||
|
17
deps/v8/src/snapshot/code-serializer.h
vendored
17
deps/v8/src/snapshot/code-serializer.h
vendored
@ -49,22 +49,9 @@ class V8_EXPORT_PRIVATE AlignedCachedData {
|
||||
int length_;
|
||||
};
|
||||
|
||||
enum class SerializedCodeSanityCheckResult {
|
||||
// Don't change order/existing values of this enum since it keys into the
|
||||
// `code_cache_reject_reason` histogram. Append-only!
|
||||
kSuccess = 0,
|
||||
kMagicNumberMismatch = 1,
|
||||
kVersionMismatch = 2,
|
||||
kSourceMismatch = 3,
|
||||
kFlagsMismatch = 5,
|
||||
kChecksumMismatch = 6,
|
||||
kInvalidHeader = 7,
|
||||
kLengthMismatch = 8,
|
||||
kReadOnlySnapshotChecksumMismatch = 9,
|
||||
typedef v8::ScriptCompiler::CachedData::CompatibilityCheckResult
|
||||
SerializedCodeSanityCheckResult;
|
||||
|
||||
// This should always point at the last real enum value.
|
||||
kLast = kReadOnlySnapshotChecksumMismatch
|
||||
};
|
||||
// If this fails, update the static_assert AND the code_cache_reject_reason
|
||||
// histogram definition.
|
||||
static_assert(static_cast<int>(SerializedCodeSanityCheckResult::kLast) == 9);
|
||||
|
72
deps/v8/test/cctest/test-serialize.cc
vendored
72
deps/v8/test/cctest/test-serialize.cc
vendored
@ -2799,6 +2799,78 @@ TEST(CodeSerializerFlagChange) {
|
||||
isolate2->Dispose();
|
||||
}
|
||||
|
||||
TEST(CachedDataCompatibilityCheck) {
|
||||
{
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
// Hand-craft a zero-filled cached data which cannot be valid.
|
||||
int length = 64;
|
||||
uint8_t* payload = new uint8_t[length];
|
||||
memset(payload, 0, length);
|
||||
v8::ScriptCompiler::CachedData cache(
|
||||
payload, length, v8::ScriptCompiler::CachedData::BufferOwned);
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate);
|
||||
v8::ScriptCompiler::CachedData::CompatibilityCheckResult result =
|
||||
cache.CompatibilityCheck(isolate);
|
||||
CHECK_NE(result, v8::ScriptCompiler::CachedData::kSuccess);
|
||||
}
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
const char* js_source = "function f() { return 'abc'; }; f() + 'def'";
|
||||
std::unique_ptr<v8::ScriptCompiler::CachedData> cache;
|
||||
{
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
v8::ScriptCompiler::Source source(v8_str(js_source),
|
||||
{isolate, v8_str("test")});
|
||||
v8::Local<v8::UnboundScript> script =
|
||||
v8::ScriptCompiler::CompileUnboundScript(
|
||||
isolate, &source, v8::ScriptCompiler::kEagerCompile)
|
||||
.ToLocalChecked();
|
||||
cache.reset(ScriptCompiler::CreateCodeCache(script));
|
||||
}
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
{
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate);
|
||||
v8::ScriptCompiler::CachedData::CompatibilityCheckResult result =
|
||||
cache->CompatibilityCheck(isolate);
|
||||
CHECK_EQ(result, v8::ScriptCompiler::CachedData::kSuccess);
|
||||
}
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
{
|
||||
v8_flags.allow_natives_syntax =
|
||||
true; // Flag change should trigger cache reject.
|
||||
FlagList::EnforceFlagImplications();
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate);
|
||||
v8::ScriptCompiler::CachedData::CompatibilityCheckResult result =
|
||||
cache->CompatibilityCheck(isolate);
|
||||
CHECK_EQ(result, v8::ScriptCompiler::CachedData::kFlagsMismatch);
|
||||
}
|
||||
isolate->Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CodeSerializerBitFlip) {
|
||||
i::v8_flags.verify_snapshot_checksum = true;
|
||||
const char* js_source = "function f() { return 'abc'; }; f() + 'def'";
|
||||
|
Loading…
x
Reference in New Issue
Block a user