[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 <vkont@google.com> Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#70336}
This commit is contained in:
parent
086eecbd96
commit
cc5498572c
@ -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.
|
||||
// -------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -1886,6 +1886,7 @@ Handle<WasmExportedFunction> 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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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],
|
||||
|
90
test/cctest/wasm/test-run-wasm-wrappers.cc
Normal file
90
test/cctest/wasm/test-run-wasm-wrappers.cc
Normal file
@ -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<v8::Isolate*>(isolate)->LowMemoryNotification();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(CallCounter) {
|
||||
{
|
||||
// This test assumes use of the generic wrapper.
|
||||
FlagScope<bool> 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<WasmModuleBuilder>(&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<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
|
||||
isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
|
||||
|
||||
MaybeHandle<WasmExportedFunction> maybe_export =
|
||||
testing::GetExportedFunction(isolate, instance.ToHandleChecked(),
|
||||
"main");
|
||||
Handle<WasmExportedFunction> 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<Object> params[2] = {Handle<Object>(Smi::FromInt(6), isolate),
|
||||
Handle<Object>(Smi::FromInt(7), isolate)};
|
||||
static const int32_t kExpectedValue = 42;
|
||||
Handle<Object> receiver = isolate->factory()->undefined_value();
|
||||
MaybeHandle<Object> maybe_result =
|
||||
Execution::Call(isolate, main_export, receiver, 2, params);
|
||||
Handle<Object> 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
|
Loading…
Reference in New Issue
Block a user