node/deps/v8/test/unittests/wasm/loop-assignment-analysis-unittest.cc
Michaël Zasso f226350fcb deps: update V8 to 11.3.244.4
PR-URL: https://github.com/nodejs/node/pull/47251
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
2023-03-31 14:15:23 +00:00

230 lines
7.1 KiB
C++

// Copyright 2016 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 "test/unittests/test-utils.h"
#include "src/init/v8.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/utils/bit-vector.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/wasm-module.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
namespace v8 {
namespace internal {
namespace wasm {
#define WASM_SET_ZERO(i) WASM_LOCAL_SET(i, WASM_ZERO)
class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
public:
WasmLoopAssignmentAnalyzerTest() : num_locals(0) {}
TestSignatures sigs;
uint32_t num_locals;
BitVector* Analyze(const byte* start, const byte* end,
bool* loop_is_innermost = nullptr) {
return AnalyzeLoopAssignmentForTesting(zone(), num_locals, start, end,
loop_is_innermost);
}
};
TEST_F(WasmLoopAssignmentAnalyzerTest, Empty0) {
byte code[] = { 0 };
BitVector* assigned = Analyze(code, code);
EXPECT_EQ(assigned, nullptr);
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
byte code[] = {kExprLoop, kVoidCode, 0};
for (int i = 0; i < 5; i++) {
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
EXPECT_FALSE(assigned->Contains(j));
}
num_locals++;
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i))};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
EXPECT_EQ(j == i, assigned->Contains(j));
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, TeeOne) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(WASM_LOCAL_TEE(i, WASM_ZERO))};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
EXPECT_EQ(j == i, assigned->Contains(j));
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
EXPECT_EQ(j == i, assigned->Contains(j));
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int k = 0; k < assigned->length(); k++) {
bool expected = k == i || k == j;
EXPECT_EQ(expected, assigned->Contains(k));
}
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
byte code[] = {WASM_LOOP(
WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = i == j || j == 0 || j == 1;
EXPECT_EQ(expected, assigned->Contains(j));
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
num_locals = 65000;
for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
byte code[] = {WASM_LOOP(WASM_I32V_1(11), kExprLocalSet, U32V_3(i))};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = i == j;
EXPECT_EQ(expected, assigned->Contains(j));
}
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
num_locals = 3;
byte code[] = {
WASM_LOOP(WASM_IF(WASM_LOCAL_GET(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
WASM_SET_ZERO(0)};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = j == 1;
EXPECT_EQ(expected, assigned->Contains(j));
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
num_locals = 5;
byte code[] = {
WASM_LOOP(WASM_IF(
WASM_LOCAL_GET(0),
WASM_BRV(0, WASM_LOCAL_SET(3, WASM_I32_SUB(WASM_LOCAL_GET(0),
WASM_I32V_1(1)))))),
WASM_LOCAL_GET(0)};
BitVector* assigned = Analyze(code, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = j == 3;
EXPECT_EQ(expected, assigned->Contains(j));
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
num_locals = 6;
const byte kIter = 0;
const byte kSum = 3;
byte code[] = {WASM_BLOCK(
WASM_WHILE(
WASM_LOCAL_GET(kIter),
WASM_BLOCK(
WASM_LOCAL_SET(
kSum, WASM_F32_ADD(WASM_LOCAL_GET(kSum),
WASM_LOAD_MEM(MachineType::Float32(),
WASM_LOCAL_GET(kIter)))),
WASM_LOCAL_SET(
kIter, WASM_I32_SUB(WASM_LOCAL_GET(kIter), WASM_I32V_1(4))))),
WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_LOCAL_GET(kSum)),
WASM_LOCAL_GET(kIter))};
BitVector* assigned = Analyze(code + 2, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = j == kIter || j == kSum;
EXPECT_EQ(expected, assigned->Contains(j));
}
}
TEST_F(WasmLoopAssignmentAnalyzerTest, NestedLoop) {
num_locals = 5;
byte code[] = {WASM_LOOP(WASM_LOOP(WASM_LOCAL_SET(0, 1)))};
bool outer_is_innermost = false;
BitVector* outer_assigned =
Analyze(code, code + arraysize(code), &outer_is_innermost);
for (int j = 0; j < outer_assigned->length(); j++) {
bool expected = j == 0;
EXPECT_EQ(expected, outer_assigned->Contains(j));
}
EXPECT_FALSE(outer_is_innermost);
bool inner_is_innermost = false;
BitVector* inner_assigned =
Analyze(code + 2, code + arraysize(code), &inner_is_innermost);
for (int j = 0; j < inner_assigned->length(); j++) {
bool expected = j == 0;
EXPECT_EQ(expected, inner_assigned->Contains(j));
}
EXPECT_TRUE(inner_is_innermost);
}
TEST_F(WasmLoopAssignmentAnalyzerTest, Malformed) {
byte code[] = {kExprLoop, kVoidCode, kExprF32Neg, kExprBrTable, 0x0E, 'h',
'e', 'l', 'l', 'o', ',', ' ',
'w', 'o', 'r', 'l', 'd', '!'};
BitVector* assigned = Analyze(code, code + arraysize(code));
EXPECT_EQ(assigned, nullptr);
}
TEST_F(WasmLoopAssignmentAnalyzerTest, InvalidOpcode) {
byte code[] = {WASM_LOOP(0xFF)};
BitVector* assigned = Analyze(code, code + arraysize(code));
EXPECT_EQ(assigned, nullptr);
}
TEST_F(WasmLoopAssignmentAnalyzerTest, regress_642867) {
static const byte code[] = {
WASM_LOOP(WASM_ZERO, kExprLocalSet, 0xFA, 0xFF, 0xFF, 0xFF,
0x0F)}; // local index LEB128 0xFFFFFFFA
// Just make sure that the analysis does not crash.
Analyze(code, code + arraysize(code));
}
#undef WASM_SET_ZERO
} // namespace wasm
} // namespace internal
} // namespace v8