[wasm] Implementation of code flushing with explicit call
This CL introduces an initial implementation of code flushing, which can be triggered from JavaScript with an explicit runtime call. The runtime call allows easier testing. So far all Liftoff code gets deallocated at a code flushing event. Experiments will show if this is a good strategy. Bug: chromium:1407659 Change-Id: I2c19a25ab5da1cf3b6d027d14cc6e719f33e300b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4171627 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/main@{#85365}
This commit is contained in:
parent
b0cd98500d
commit
10f3039bdb
@ -489,6 +489,19 @@ RUNTIME_FUNCTION(Runtime_IsTurboFanFunction) {
|
||||
return isolate->heap()->ToBoolean(code && code->is_turbofan());
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_IsUncompiledWasmFunction) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
Handle<JSFunction> function = args.at<JSFunction>(0);
|
||||
CHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
|
||||
Handle<WasmExportedFunction> exp_fun =
|
||||
Handle<WasmExportedFunction>::cast(function);
|
||||
wasm::NativeModule* native_module =
|
||||
exp_fun->instance().module_object().native_module();
|
||||
uint32_t func_index = exp_fun->function_index();
|
||||
return isolate->heap()->ToBoolean(!native_module->HasCode(func_index));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
|
||||
DCHECK_EQ(1, args.length());
|
||||
DisallowGarbageCollection no_gc;
|
||||
@ -510,5 +523,10 @@ RUNTIME_FUNCTION(Runtime_SetWasmGCEnabled) {
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_FlushWasmCode) {
|
||||
wasm::GetWasmEngine()->FlushCode();
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -654,6 +654,7 @@ namespace internal {
|
||||
#define FOR_EACH_INTRINSIC_WASM_TEST(F, I) \
|
||||
F(DeserializeWasmModule, 2, 1) \
|
||||
F(DisallowWasmCodegen, 1, 1) \
|
||||
F(FlushWasmCode, 0, 1) \
|
||||
F(FreezeWasmLazyCompilation, 1, 1) \
|
||||
F(GetWasmExceptionTagId, 2, 1) \
|
||||
F(GetWasmExceptionValues, 1, 1) \
|
||||
@ -662,6 +663,7 @@ namespace internal {
|
||||
F(IsLiftoffFunction, 1, 1) \
|
||||
F(IsTurboFanFunction, 1, 1) \
|
||||
F(IsWasmDebugFunction, 1, 1) \
|
||||
F(IsUncompiledWasmFunction, 1, 1) \
|
||||
F(IsThreadInWasm, 0, 1) \
|
||||
F(IsWasmCode, 1, 1) \
|
||||
F(IsWasmTrapHandlerEnabled, 0, 1) \
|
||||
|
@ -2230,6 +2230,10 @@ bool ShouldRemoveCode(WasmCode* code, NativeModule::RemoveFilter filter) {
|
||||
code->for_debugging()) {
|
||||
return false;
|
||||
}
|
||||
if (filter == NativeModule::RemoveFilter::kRemoveLiftoffCode &&
|
||||
!code->is_liftoff()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -794,6 +794,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
|
||||
enum class RemoveFilter {
|
||||
kRemoveDebugCode,
|
||||
kRemoveNonDebugCode,
|
||||
kRemoveLiftoffCode,
|
||||
kRemoveAllCode,
|
||||
};
|
||||
// Remove all compiled code from the {NativeModule} and replace it with
|
||||
|
@ -893,6 +893,14 @@ Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
|
||||
return module_object;
|
||||
}
|
||||
|
||||
void WasmEngine::FlushCode() {
|
||||
for (auto& entry : native_modules_) {
|
||||
NativeModule* native_module = entry.first;
|
||||
native_module->RemoveCompiledCode(
|
||||
NativeModule::RemoveFilter::kRemoveLiftoffCode);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CompilationStatistics>
|
||||
WasmEngine::GetOrCreateTurboStatistics() {
|
||||
base::MutexGuard guard(&mutex_);
|
||||
|
@ -220,6 +220,8 @@ class V8_EXPORT_PRIVATE WasmEngine {
|
||||
Isolate* isolate, std::shared_ptr<NativeModule> shared_module,
|
||||
base::Vector<const char> source_url);
|
||||
|
||||
void FlushCode();
|
||||
|
||||
AccountingAllocator* allocator() { return &allocator_; }
|
||||
|
||||
// Compilation statistics for TurboFan compilations. Returns a shared_ptr
|
||||
|
@ -989,6 +989,7 @@
|
||||
# multiple isolates, as dynamic tiering relies on a array shared
|
||||
# in the module, that can be modified by all instances.
|
||||
'wasm/wasm-dynamic-tiering': [SKIP],
|
||||
'wasm/code-flushing': [SKIP],
|
||||
|
||||
# The test relies on precise switching of code kinds of wasm functions. With
|
||||
# multiple isolates that share the wasm functions, the precise switching is
|
||||
|
40
test/mjsunit/wasm/code-flushing.js
Normal file
40
test/mjsunit/wasm/code-flushing.js
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2023 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --expose-wasm --allow-natives-syntax --wasm-lazy-compilation
|
||||
|
||||
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
const builder = new WasmModuleBuilder();
|
||||
builder.addFunction('f1', kSig_i_i).addBody([kExprLocalGet, 0]).exportFunc();
|
||||
builder.addFunction('f2', kSig_i_i).addBody([kExprLocalGet, 0]).exportFunc();
|
||||
builder.addFunction('f3', kSig_i_i).addBody([kExprLocalGet, 0]).exportFunc();
|
||||
|
||||
const instance = builder.instantiate();
|
||||
|
||||
instance.exports.f1(1);
|
||||
instance.exports.f2(2);
|
||||
instance.exports.f3(3);
|
||||
|
||||
assertTrue(%IsLiftoffFunction(instance.exports.f1));
|
||||
assertTrue(%IsLiftoffFunction(instance.exports.f2));
|
||||
assertTrue(%IsLiftoffFunction(instance.exports.f3));
|
||||
|
||||
%FlushWasmCode();
|
||||
|
||||
assertTrue(%IsUncompiledWasmFunction(instance.exports.f1));
|
||||
assertTrue(%IsUncompiledWasmFunction(instance.exports.f2));
|
||||
assertTrue(%IsUncompiledWasmFunction(instance.exports.f3));
|
||||
|
||||
instance.exports.f1(1);
|
||||
instance.exports.f2(2);
|
||||
instance.exports.f3(3);
|
||||
|
||||
%WasmTierUpFunction(instance.exports.f3);
|
||||
|
||||
%FlushWasmCode();
|
||||
|
||||
assertTrue(%IsUncompiledWasmFunction(instance.exports.f1));
|
||||
assertTrue(%IsUncompiledWasmFunction(instance.exports.f2));
|
||||
assertTrue(%IsTurboFanFunction(instance.exports.f3));
|
Loading…
Reference in New Issue
Block a user