v8/test/cctest/wasm/test-c-wasm-entry.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

198 lines
7.2 KiB
C++
Raw Normal View History

// Copyright 2017 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 <cstdint>
#include "src/assembler-inl.h"
#include "src/objects-inl.h"
#include "src/wasm/wasm-objects.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
#include "test/cctest/wasm/wasm-run-utils.h"
#include "test/common/wasm/wasm-macro-gen.h"
namespace v8 {
namespace internal {
namespace wasm {
/**
* We test the interface from C to compiled wasm code by generating a wasm
* function, creating a corresponding signature, compiling the c wasm entry for
* that signature, and then calling that entry using different test values.
* The result is compared against the expected result, computed from a lambda
* passed to the CWasmEntryArgTester.
*/
namespace {
template <typename ReturnType, typename... Args>
class CWasmEntryArgTester {
public:
CWasmEntryArgTester(std::initializer_list<uint8_t> wasm_function_bytes,
std::function<ReturnType(Args...)> expected_fn)
: runner_(kExecuteTurbofan),
isolate_(runner_.main_isolate()),
expected_fn_(expected_fn),
sig_(runner_.template CreateSig<ReturnType, Args...>()) {
std::vector<uint8_t> code{wasm_function_bytes};
runner_.Build(code.data(), code.data() + code.size());
Revert "Revert "[wasm] Rename TestingModule to TestingModuleBuilder."" This reverts commit 3913bde18848f95df41dc42627b826cb41231894. Reason for revert: Reason for revert fixed. Original change's description: > Revert "[wasm] Rename TestingModule to TestingModuleBuilder." > > This reverts commit ed06fc9127d2f965ece485293d2bc67fc6e0fb53. > > Reason for revert: Need to revert previous CL > > Original change's description: > > [wasm] Rename TestingModule to TestingModuleBuilder. > > > > This is a followup to moving the ModuleEnv to the compiler directory and > > making it immutable. > > > > R=​mtrofin@chromium.org, ahaas@chromium.org > > > > Bug: > > Change-Id: I0f5ec1b697bdcfad0b4dc2bca577cc0f40de8dc0 > > Reviewed-on: https://chromium-review.googlesource.com/616762 > > Commit-Queue: Ben Titzer <titzer@chromium.org> > > Reviewed-by: Mircea Trofin <mtrofin@chromium.org> > > Reviewed-by: Andreas Haas <ahaas@chromium.org> > > Cr-Commit-Position: refs/heads/master@{#47419} > > TBR=titzer@chromium.org,mtrofin@chromium.org,ahaas@chromium.org > > Change-Id: I9b3b379e89f523c2fcf205a1d268aa294bbc44ff > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://chromium-review.googlesource.com/622567 > Reviewed-by: Michael Achenbach <machenbach@chromium.org> > Commit-Queue: Michael Achenbach <machenbach@chromium.org> > Cr-Commit-Position: refs/heads/master@{#47448} TBR=machenbach@chromium.org,titzer@chromium.org,mtrofin@chromium.org,ahaas@chromium.org Change-Id: Idce6f1ca8ed0ea80edb50292e9b6e2d7712f29cf No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/622034 Reviewed-by: Mircea Trofin <mtrofin@chromium.org> Commit-Queue: Mircea Trofin <mtrofin@chromium.org> Cr-Commit-Position: refs/heads/master@{#47454}
2017-08-19 16:34:11 +00:00
wasm_code_ = runner_.builder().GetFunctionCode(0);
Handle<WasmInstanceObject> instance(runner_.builder().instance_object());
Handle<WasmDebugInfo> debug_info =
WasmInstanceObject::GetOrCreateDebugInfo(instance);
c_wasm_entry_fn_ = WasmDebugInfo::GetCWasmEntry(debug_info, sig_);
}
template <typename... Rest>
void WriteToBuffer(uint8_t* buf, Rest... rest) {
static_assert(sizeof...(rest) == 0, "this is the base case");
}
template <typename First, typename... Rest>
void WriteToBuffer(uint8_t* buf, First first, Rest... rest) {
WriteUnalignedValue(buf, first);
WriteToBuffer(buf + sizeof(first), rest...);
}
void CheckCall(Args... args) {
std::vector<uint8_t> arg_buffer(sizeof...(args) * 8);
WriteToBuffer(arg_buffer.data(), args...);
Handle<Object> receiver = isolate_->factory()->undefined_value();
Handle<Object> buffer_obj(reinterpret_cast<Object*>(arg_buffer.data()),
isolate_);
CHECK(!buffer_obj->IsHeapObject());
WasmContext* wasm_context = wasm_code_->owner()
->compiled_module()
->owning_instance()
->wasm_context()
->get();
Revert "Revert "[wasm] JIT using WasmCodeManager"" This reverts commit b301203e5aec9c8ff32f93aa31f8d764311e6e6e. Reason for revert: Fixed issues on arm. Original change's description: > Revert "[wasm] JIT using WasmCodeManager" > > This reverts commit d4c8393c1cc9cf3e2b19daabc3a161ff18d596cb. > > Reason for revert: Breaks ARM hardware: > https://build.chromium.org/p/client.v8.ports/builders/V8%20Arm%20-%20debug/builds/5268 > > Original change's description: > > [wasm] JIT using WasmCodeManager > > > > This is the first step towards wasm code sharing. This CL moves wasm > > code generation outside the JavaScript GC heap using the previously - > > introduced WasmCodeManager (all this, behind the --wasm-jit-to-native > > flag). > > > > See design document: go/wasm-on-native-heap-stage-1 > > > > This CL doesn't change other wasm architectural invariants. We still > > have per-Isolate wasm code generation, and per-wasm module instance > > code specialization. > > > > Bug:v8:6876 > > > > Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng > > Change-Id: I1e08cecad75f93fb081545c31228a4568be276d3 > > Reviewed-on: https://chromium-review.googlesource.com/674086 > > Reviewed-by: Ben Titzer <titzer@chromium.org> > > Reviewed-by: Eric Holk <eholk@chromium.org> > > Cr-Commit-Position: refs/heads/master@{#49689} > > TBR=bradnelson@chromium.org,titzer@chromium.org,mtrofin@chromium.org,eholk@chromium.org > > Change-Id: I89af1ea5decd841bc12cd2ceaf74d32bc4433885 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: v8:6876 > Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng > Reviewed-on: https://chromium-review.googlesource.com/794690 > Reviewed-by: Michael Achenbach <machenbach@chromium.org> > Commit-Queue: Michael Achenbach <machenbach@chromium.org> > Cr-Commit-Position: refs/heads/master@{#49691} TBR=bradnelson@chromium.org,machenbach@chromium.org,titzer@chromium.org,mtrofin@chromium.org,eholk@chromium.org Change-Id: I1b07638d1bb2ba0664305b4b2dcfc1342dc8444f No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:6876 Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng Reviewed-on: https://chromium-review.googlesource.com/794434 Commit-Queue: Mircea Trofin <mtrofin@chromium.org> Reviewed-by: Mircea Trofin <mtrofin@chromium.org> Cr-Commit-Position: refs/heads/master@{#49692}
2017-11-28 22:25:36 +00:00
Handle<Object> call_args[]{
Handle<Object>::cast(isolate_->factory()->NewForeign(
wasm_code_->instructions().start(), TENURED)),
handle(reinterpret_cast<Object*>(wasm_context), isolate_), buffer_obj};
static_assert(
arraysize(call_args) == compiler::CWasmEntryParameters::kNumParameters,
"adapt this test");
wasm_code_->owner()->SetExecutable(true);
MaybeHandle<Object> return_obj = Execution::Call(
isolate_, c_wasm_entry_fn_, receiver, arraysize(call_args), call_args);
CHECK(!return_obj.is_null());
CHECK(return_obj.ToHandleChecked()->IsSmi());
CHECK_EQ(0, Smi::ToInt(*return_obj.ToHandleChecked()));
// Check the result.
ReturnType result = ReadUnalignedValue<ReturnType>(arg_buffer.data());
ReturnType expected = expected_fn_(args...);
if (std::is_floating_point<ReturnType>::value) {
CHECK_DOUBLE_EQ(expected, result);
} else {
CHECK_EQ(expected, result);
}
}
private:
WasmRunner<ReturnType, Args...> runner_;
Isolate* isolate_;
std::function<ReturnType(Args...)> expected_fn_;
FunctionSig* sig_;
Handle<JSFunction> c_wasm_entry_fn_;
wasm::WasmCode* wasm_code_;
};
} // namespace
// Pass int32_t, return int32_t.
TEST(TestCWasmEntryArgPassing_int32) {
CWasmEntryArgTester<int32_t, int32_t> tester(
{// Return 2*<0> + 1.
WASM_I32_ADD(WASM_I32_MUL(WASM_I32V_1(2), WASM_GET_LOCAL(0)), WASM_ONE)},
[](int32_t a) { return 2 * a + 1; });
FOR_INT32_INPUTS(v) { tester.CheckCall(*v); }
}
// Pass int64_t, return double.
TEST(TestCWasmEntryArgPassing_double_int64) {
CWasmEntryArgTester<double, int64_t> tester(
{// Return (double)<0>.
WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0))},
[](int64_t a) { return static_cast<double>(a); });
FOR_INT64_INPUTS(v) { tester.CheckCall(*v); }
}
// Pass double, return int64_t.
TEST(TestCWasmEntryArgPassing_int64_double) {
CWasmEntryArgTester<int64_t, double> tester(
{// Return (int64_t)<0>.
WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))},
[](double d) { return static_cast<int64_t>(d); });
FOR_INT64_INPUTS(i) { tester.CheckCall(*i); }
}
// Pass float, return double.
TEST(TestCWasmEntryArgPassing_float_double) {
CWasmEntryArgTester<double, float> tester(
{// Return 2*(double)<0> + 1.
WASM_F64_ADD(
WASM_F64_MUL(WASM_F64(2), WASM_F64_CONVERT_F32(WASM_GET_LOCAL(0))),
WASM_F64(1))},
[](float f) { return 2. * static_cast<double>(f) + 1.; });
FOR_FLOAT32_INPUTS(f) { tester.CheckCall(*f); }
}
// Pass two doubles, return double.
TEST(TestCWasmEntryArgPassing_double_double) {
CWasmEntryArgTester<double, double, double> tester(
{// Return <0> + <1>.
WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))},
[](double a, double b) { return a + b; });
FOR_FLOAT64_INPUTS(d1) {
FOR_FLOAT64_INPUTS(d2) { tester.CheckCall(*d1, *d2); }
}
}
// Pass int32_t, int64_t, float and double, return double.
TEST(TestCWasmEntryArgPassing_AllTypes) {
CWasmEntryArgTester<double, int32_t, int64_t, float, double> tester(
{
// Convert all arguments to double, add them and return the sum.
WASM_F64_ADD( // <0+1+2> + <3>
WASM_F64_ADD( // <0+1> + <2>
WASM_F64_ADD( // <0> + <1>
WASM_F64_SCONVERT_I32(
WASM_GET_LOCAL(0)), // <0> to double
WASM_F64_SCONVERT_I64(
WASM_GET_LOCAL(1))), // <1> to double
WASM_F64_CONVERT_F32(WASM_GET_LOCAL(2))), // <2> to double
WASM_GET_LOCAL(3)) // <3>
},
[](int32_t a, int64_t b, float c, double d) {
return 0. + a + b + c + d;
});
Vector<const int32_t> test_values_i32 = compiler::ValueHelper::int32_vector();
Vector<const int64_t> test_values_i64 = compiler::ValueHelper::int64_vector();
Vector<const float> test_values_f32 = compiler::ValueHelper::float32_vector();
Vector<const double> test_values_f64 =
compiler::ValueHelper::float64_vector();
size_t max_len =
std::max(std::max(test_values_i32.size(), test_values_i64.size()),
std::max(test_values_f32.size(), test_values_f64.size()));
for (size_t i = 0; i < max_len; ++i) {
int32_t i32 = test_values_i32[i % test_values_i32.size()];
int64_t i64 = test_values_i64[i % test_values_i64.size()];
float f32 = test_values_f32[i % test_values_f32.size()];
double f64 = test_values_f64[i % test_values_f64.size()];
tester.CheckCall(i32, i64, f32, f64);
}
}
} // namespace wasm
} // namespace internal
} // namespace v8