From cc5498572c62cd35044c6540664ae480ccf64074 Mon Sep 17 00:00:00 2001 From: Vicky Kontoura Date: Tue, 6 Oct 2020 09:46:56 +0000 Subject: [PATCH] [wasm] Count calls to exported functions This CL adds a call counter in the WasmExportedFunctionData. The counter is incremented every time a call to an exported WebAssembly function is handled through the generic js-to-wasm wrapper. Bug: v8:10982 Change-Id: Iad40b414b0c7d2f4ab340ff4ebb7b24c60b3a974 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2445873 Commit-Queue: Vicky Kontoura Reviewed-by: Andreas Haas Reviewed-by: Jakob Kummerow Cr-Commit-Position: refs/heads/master@{#70336} --- src/builtins/x64/builtins-x64.cc | 8 ++ src/objects/shared-function-info.h | 3 +- src/wasm/wasm-objects-inl.h | 1 + src/wasm/wasm-objects.cc | 1 + src/wasm/wasm-objects.h | 1 + src/wasm/wasm-objects.tq | 1 + test/cctest/BUILD.gn | 1 + test/cctest/cctest.status | 1 + test/cctest/wasm/test-run-wasm-wrappers.cc | 90 ++++++++++++++++++++++ 9 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 test/cctest/wasm/test-run-wasm-wrappers.cc diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index f0623da0d9..dac9ec9f69 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -3362,6 +3362,14 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) { MemOperand(function_data, WasmExportedFunctionData::kInstanceOffset - kHeapObjectTag)); + // ------------------------------------------- + // Increment the call count in function data. + // ------------------------------------------- + __ SmiAddConstant( + MemOperand(function_data, + WasmExportedFunctionData::kCallCountOffset - kHeapObjectTag), + Smi::FromInt(1)); + // ------------------------------------------- // Load values from the signature. // ------------------------------------------- diff --git a/src/objects/shared-function-info.h b/src/objects/shared-function-info.h index 5abcec8ec6..c4e03ba63e 100644 --- a/src/objects/shared-function-info.h +++ b/src/objects/shared-function-info.h @@ -337,7 +337,8 @@ class SharedFunctionInfo : public HeapObject { UncompiledDataWithPreparseData data); inline bool HasUncompiledDataWithoutPreparseData() const; inline bool HasWasmExportedFunctionData() const; - WasmExportedFunctionData wasm_exported_function_data() const; + V8_EXPORT_PRIVATE WasmExportedFunctionData + wasm_exported_function_data() const; inline bool HasWasmJSFunctionData() const; WasmJSFunctionData wasm_js_function_data() const; inline bool HasWasmCapiFunctionData() const; diff --git a/src/wasm/wasm-objects-inl.h b/src/wasm/wasm-objects-inl.h index 3accc86418..4c0f2429ac 100644 --- a/src/wasm/wasm-objects-inl.h +++ b/src/wasm/wasm-objects-inl.h @@ -329,6 +329,7 @@ ACCESSORS(WasmExportedFunctionData, instance, WasmInstanceObject, SMI_ACCESSORS(WasmExportedFunctionData, jump_table_offset, kJumpTableOffsetOffset) SMI_ACCESSORS(WasmExportedFunctionData, function_index, kFunctionIndexOffset) +SMI_ACCESSORS(WasmExportedFunctionData, call_count, kCallCountOffset) ACCESSORS(WasmExportedFunctionData, c_wrapper_code, Object, kCWrapperCodeOffset) ACCESSORS(WasmExportedFunctionData, wasm_call_target, Object, kWasmCallTargetOffset) diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc index 396d6ebb01..e4499664b6 100644 --- a/src/wasm/wasm-objects.cc +++ b/src/wasm/wasm-objects.cc @@ -1886,6 +1886,7 @@ Handle WasmExportedFunction::New( function_data->set_instance(*instance); function_data->set_jump_table_offset(jump_table_offset); function_data->set_function_index(func_index); + function_data->set_call_count(0); function_data->set_c_wrapper_code(Smi::zero(), SKIP_WRITE_BARRIER); function_data->set_wasm_call_target(Smi::zero(), SKIP_WRITE_BARRIER); function_data->set_packed_args_size(0); diff --git a/src/wasm/wasm-objects.h b/src/wasm/wasm-objects.h index 5b97ae5c31..de70debd16 100644 --- a/src/wasm/wasm-objects.h +++ b/src/wasm/wasm-objects.h @@ -783,6 +783,7 @@ class WasmExportedFunctionData : public Struct { DECL_ACCESSORS(instance, WasmInstanceObject) DECL_INT_ACCESSORS(jump_table_offset) DECL_INT_ACCESSORS(function_index) + DECL_INT_ACCESSORS(call_count) DECL_ACCESSORS(c_wrapper_code, Object) DECL_ACCESSORS(wasm_call_target, Object) DECL_INT_ACCESSORS(packed_args_size) diff --git a/src/wasm/wasm-objects.tq b/src/wasm/wasm-objects.tq index bd1fdfd783..8ed2651d2e 100644 --- a/src/wasm/wasm-objects.tq +++ b/src/wasm/wasm-objects.tq @@ -15,6 +15,7 @@ extern class WasmExportedFunctionData extends Struct { instance: WasmInstanceObject; jump_table_offset: Smi; function_index: Smi; + call_count: Smi; // The remaining fields are for fast calling from C++. The contract is // that they are lazily populated, and either all will be present or none. c_wrapper_code: Object; diff --git a/test/cctest/BUILD.gn b/test/cctest/BUILD.gn index e93410dd49..95330aab47 100644 --- a/test/cctest/BUILD.gn +++ b/test/cctest/BUILD.gn @@ -303,6 +303,7 @@ v8_source_set("cctest_sources") { "wasm/test-run-wasm-simd-liftoff.cc", "wasm/test-run-wasm-simd-scalar-lowering.cc", "wasm/test-run-wasm-simd.cc", + "wasm/test-run-wasm-wrappers.cc", "wasm/test-run-wasm.cc", "wasm/test-streaming-compilation.cc", "wasm/test-wasm-breakpoints.cc", diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 4f00dea457..2f36791b8c 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -517,6 +517,7 @@ 'test-run-wasm-simd-liftoff/*': [SKIP], 'test-run-wasm-simd-scalar-lowering/*': [SKIP], 'test-run-wasm-simd/*': [SKIP], + 'test-run-wasm-wrappers/*': [SKIP], 'test-streaming-compilation/*': [SKIP], 'test-wasm-breakpoints/*': [SKIP], 'test-wasm-codegen/*': [SKIP], diff --git a/test/cctest/wasm/test-run-wasm-wrappers.cc b/test/cctest/wasm/test-run-wasm-wrappers.cc new file mode 100644 index 0000000000..0b2b93c6b6 --- /dev/null +++ b/test/cctest/wasm/test-run-wasm-wrappers.cc @@ -0,0 +1,90 @@ +// Copyright 2020 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. + +#include "src/wasm/wasm-module-builder.h" +#include "src/wasm/wasm-objects-inl.h" +#include "test/cctest/cctest.h" +#include "test/common/wasm/flag-utils.h" +#include "test/common/wasm/test-signatures.h" +#include "test/common/wasm/wasm-macro-gen.h" +#include "test/common/wasm/wasm-module-runner.h" + +namespace v8 { +namespace internal { +namespace wasm { +namespace test_run_wasm_wrappers { + +using testing::CompileAndInstantiateForTesting; + +#ifdef V8_TARGET_ARCH_X64 +namespace { +void Cleanup() { + // By sending a low memory notifications, we will try hard to collect all + // garbage and will therefore also invoke all weak callbacks of actually + // unreachable persistent handles. + Isolate* isolate = CcTest::InitIsolateOnce(); + reinterpret_cast(isolate)->LowMemoryNotification(); +} + +} // namespace + +TEST(CallCounter) { + { + // This test assumes use of the generic wrapper. + FlagScope use_wasm_generic_wrapper(&FLAG_wasm_generic_wrapper, true); + + TestSignatures sigs; + AccountingAllocator allocator; + Zone zone(&allocator, ZONE_NAME); + + // Define the Wasm function. + WasmModuleBuilder* builder = zone.New(&zone); + WasmFunctionBuilder* f = builder->AddFunction(sigs.i_ii()); + f->builder()->AddExport(CStrVector("main"), f); + byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), + WASM_END}; + f->EmitCode(code, sizeof(code)); + + // Compile module. + ZoneBuffer buffer(&zone); + builder->WriteTo(&buffer); + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + testing::SetupIsolateForWasmModule(isolate); + ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); + MaybeHandle instance = CompileAndInstantiateForTesting( + isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end())); + + MaybeHandle maybe_export = + testing::GetExportedFunction(isolate, instance.ToHandleChecked(), + "main"); + Handle main_export = maybe_export.ToHandleChecked(); + + // Check that the counter has initially a value of 0. + CHECK_EQ(main_export->shared().wasm_exported_function_data().call_count(), + 0); + + // Call the exported Wasm function and get the result. + Handle params[2] = {Handle(Smi::FromInt(6), isolate), + Handle(Smi::FromInt(7), isolate)}; + static const int32_t kExpectedValue = 42; + Handle receiver = isolate->factory()->undefined_value(); + MaybeHandle maybe_result = + Execution::Call(isolate, main_export, receiver, 2, params); + Handle result = maybe_result.ToHandleChecked(); + + // Check that the counter has now a value of 1. + CHECK_EQ(main_export->shared().wasm_exported_function_data().call_count(), + 1); + + CHECK(result->IsSmi() && Smi::ToInt(*result) == kExpectedValue); + } + Cleanup(); +} +#endif + +} // namespace test_run_wasm_wrappers +} // namespace wasm +} // namespace internal +} // namespace v8