v8/test/wasm-api-tests/wasm-api-test.h
Hisham Muhammad 0f748aac3e [wasm][c-api] Add handle scope to fix wasm_module_validate
This adds a handle scope to Module::validate in C API
so that the wasm_module_validate can be usable from C.

Without the added handle scope, attempting to call
wasm_module_validate function from C code fails with:

    #
    # Fatal error in v8::HandleScope::CreateHandle()
    # Cannot create a handle without a HandleScope
    #

Bug: v8:12941
Change-Id: I2b4d5dccdaed9501f31447158ebf8e7906a1f8f0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3692020
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81048}
2022-06-09 16:46:23 +00:00

184 lines
5.3 KiB
C++

// Copyright 2019 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.
#ifndef TEST_WASM_API_TESTS_WASM_API_TEST_H_
#define TEST_WASM_API_TESTS_WASM_API_TEST_H_
#include "src/wasm/wasm-module-builder.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/accounting-allocator.h"
#include "src/zone/zone.h"
#include "test/common/wasm/wasm-macro-gen.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/wasm-api/wasm.hh"
namespace v8 {
namespace internal {
namespace wasm {
using ::wasm::Engine;
using ::wasm::Extern;
using ::wasm::Foreign;
using ::wasm::Func;
using ::wasm::FuncType;
using ::wasm::Global;
using ::wasm::Instance;
using ::wasm::Memory;
using ::wasm::Module;
using ::wasm::own;
using ::wasm::ownvec;
using ::wasm::Ref;
using ::wasm::Store;
using ::wasm::Table;
using ::wasm::Trap;
using ::wasm::Val;
using ::wasm::ValType;
using ::wasm::vec;
class WasmCapiTest : public ::testing::Test {
public:
WasmCapiTest()
: Test(),
engine_(Engine::make()),
allocator_(std::make_unique<AccountingAllocator>()),
zone_(std::make_unique<Zone>(allocator_.get(), ZONE_NAME)),
wire_bytes_(zone_.get()),
builder_(zone_->New<WasmModuleBuilder>(zone_.get())),
exports_(ownvec<Extern>::make()),
binary_(vec<byte_t>::make()),
wasm_i_i_sig_(1, 1, wasm_i_i_sig_types_) {
store_ = Store::make(engine_.get());
cpp_i_i_sig_ =
FuncType::make(ownvec<ValType>::make(ValType::make(::wasm::I32)),
ownvec<ValType>::make(ValType::make(::wasm::I32)));
}
bool Validate() {
if (binary_.size() == 0) {
builder_->WriteTo(&wire_bytes_);
size_t size = wire_bytes_.end() - wire_bytes_.begin();
binary_ = vec<byte_t>::make(
size,
reinterpret_cast<byte_t*>(const_cast<byte*>(wire_bytes_.begin())));
}
return Module::validate(store_.get(), binary_);
}
void Compile() {
if (binary_.size() == 0) {
builder_->WriteTo(&wire_bytes_);
size_t size = wire_bytes_.end() - wire_bytes_.begin();
binary_ = vec<byte_t>::make(
size,
reinterpret_cast<byte_t*>(const_cast<byte*>(wire_bytes_.begin())));
}
module_ = Module::make(store_.get(), binary_);
DCHECK_NE(module_.get(), nullptr);
}
void Instantiate(Extern* imports[]) {
Compile();
instance_ = Instance::make(store_.get(), module_.get(), imports);
DCHECK_NE(instance_.get(), nullptr);
exports_ = instance_->exports();
}
void AddExportedFunction(base::Vector<const char> name, byte code[],
size_t code_size, FunctionSig* sig) {
WasmFunctionBuilder* fun = builder()->AddFunction(sig);
fun->EmitCode(code, static_cast<uint32_t>(code_size));
fun->Emit(kExprEnd);
builder()->AddExport(name, fun);
}
void AddFunction(byte code[], size_t code_size, FunctionSig* sig) {
WasmFunctionBuilder* fun = builder()->AddFunction(sig);
fun->EmitCode(code, static_cast<uint32_t>(code_size));
fun->Emit(kExprEnd);
}
Func* GetExportedFunction(size_t index) {
DCHECK_GT(exports_.size(), index);
Extern* exported = exports_[index].get();
DCHECK_EQ(exported->kind(), ::wasm::EXTERN_FUNC);
Func* func = exported->func();
DCHECK_NE(func, nullptr);
return func;
}
Global* GetExportedGlobal(size_t index) {
DCHECK_GT(exports_.size(), index);
Extern* exported = exports_[index].get();
DCHECK_EQ(exported->kind(), ::wasm::EXTERN_GLOBAL);
Global* global = exported->global();
DCHECK_NE(global, nullptr);
return global;
}
Memory* GetExportedMemory(size_t index) {
DCHECK_GT(exports_.size(), index);
Extern* exported = exports_[index].get();
DCHECK_EQ(exported->kind(), ::wasm::EXTERN_MEMORY);
Memory* memory = exported->memory();
DCHECK_NE(memory, nullptr);
return memory;
}
Table* GetExportedTable(size_t index) {
DCHECK_GT(exports_.size(), index);
Extern* exported = exports_[index].get();
DCHECK_EQ(exported->kind(), ::wasm::EXTERN_TABLE);
Table* table = exported->table();
DCHECK_NE(table, nullptr);
return table;
}
void ResetModule() { module_.reset(); }
void Shutdown() {
exports_.reset();
instance_.reset();
module_.reset();
store_.reset();
builder_ = nullptr;
zone_.reset();
allocator_.reset();
engine_.reset();
}
WasmModuleBuilder* builder() { return builder_; }
Engine* engine() { return engine_.get(); }
Store* store() { return store_.get(); }
Module* module() { return module_.get(); }
Instance* instance() { return instance_.get(); }
const ownvec<Extern>& exports() { return exports_; }
ZoneBuffer* wire_bytes() { return &wire_bytes_; }
FunctionSig* wasm_i_i_sig() { return &wasm_i_i_sig_; }
FuncType* cpp_i_i_sig() { return cpp_i_i_sig_.get(); }
private:
own<Engine> engine_;
own<AccountingAllocator> allocator_;
own<Zone> zone_;
ZoneBuffer wire_bytes_;
WasmModuleBuilder* builder_;
own<Store> store_;
own<Module> module_;
own<Instance> instance_;
ownvec<Extern> exports_;
vec<byte_t> binary_;
own<FuncType> cpp_i_i_sig_;
ValueType wasm_i_i_sig_types_[2] = {kWasmI32, kWasmI32};
FunctionSig wasm_i_i_sig_;
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // TEST_WASM_API_TESTS_WASM_API_TEST_H_