2016-01-25 10:27:29 +00:00
|
|
|
// 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"
|
|
|
|
|
2019-05-24 13:51:59 +00:00
|
|
|
#include "src/init/v8.h"
|
2019-05-23 08:51:46 +00:00
|
|
|
#include "src/objects/objects-inl.h"
|
|
|
|
#include "src/objects/objects.h"
|
2019-05-24 13:51:59 +00:00
|
|
|
#include "src/utils/bit-vector.h"
|
2016-12-21 12:42:06 +00:00
|
|
|
#include "src/wasm/function-body-decoder.h"
|
2016-01-25 10:27:29 +00:00
|
|
|
#include "src/wasm/wasm-module.h"
|
|
|
|
|
2017-04-25 11:29:17 +00:00
|
|
|
#include "test/common/wasm/test-signatures.h"
|
|
|
|
#include "test/common/wasm/wasm-macro-gen.h"
|
|
|
|
|
2016-01-25 10:27:29 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace wasm {
|
|
|
|
|
2020-12-17 16:55:33 +00:00
|
|
|
#define WASM_SET_ZERO(i) WASM_LOCAL_SET(i, WASM_ZERO)
|
2017-09-08 13:59:05 +00:00
|
|
|
|
2016-01-25 10:27:29 +00:00
|
|
|
class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
|
|
|
|
public:
|
2016-03-07 21:04:07 +00:00
|
|
|
WasmLoopAssignmentAnalyzerTest() : num_locals(0) {}
|
2016-01-25 10:27:29 +00:00
|
|
|
TestSignatures sigs;
|
2016-03-07 21:04:07 +00:00
|
|
|
uint32_t num_locals;
|
2016-01-25 10:27:29 +00:00
|
|
|
|
|
|
|
BitVector* Analyze(const byte* start, const byte* end) {
|
2016-03-07 21:04:07 +00:00
|
|
|
return AnalyzeLoopAssignmentForTesting(zone(), num_locals, start, end);
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Empty0) {
|
|
|
|
byte code[] = { 0 };
|
|
|
|
BitVector* assigned = Analyze(code, code);
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(assigned, nullptr);
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
|
2020-09-29 07:46:36 +00:00
|
|
|
byte code[] = {kExprLoop, kVoidCode, 0};
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_FALSE(assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals++;
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 5;
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 0; i < 5; i++) {
|
2016-07-21 11:04:06 +00:00
|
|
|
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i))};
|
2016-01-25 10:27:29 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(j == i, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 20:46:10 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, TeeOne) {
|
|
|
|
num_locals = 5;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
2020-12-17 16:55:33 +00:00
|
|
|
byte code[] = {WASM_LOOP(WASM_LOCAL_TEE(i, WASM_ZERO))};
|
2016-09-27 20:46:10 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(j == i, assigned->Contains(j));
|
2016-09-27 20:46:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 10:27:29 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 5;
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 0; i < 5; i++) {
|
2016-07-21 11:04:06 +00:00
|
|
|
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
|
2016-01-25 10:27:29 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(j == i, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 5;
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
for (int j = 0; j < 5; j++) {
|
2016-07-21 11:04:06 +00:00
|
|
|
byte code[] = {WASM_LOOP(WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
|
2016-01-25 10:27:29 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int k = 0; k < assigned->length(); k++) {
|
|
|
|
bool expected = k == i || k == j;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(k));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 5;
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
byte code[] = {WASM_LOOP(
|
2016-07-21 11:04:06 +00:00
|
|
|
WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
|
2016-01-25 10:27:29 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
|
|
|
bool expected = i == j || j == 0 || j == 1;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 65000;
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
|
2019-10-08 12:38:48 +00:00
|
|
|
byte code[] = {WASM_LOOP(WASM_I32V_1(11), kExprLocalSet, U32V_3(i))};
|
2016-01-25 10:27:29 +00:00
|
|
|
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
|
|
|
bool expected = i == j;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 3;
|
2016-01-25 10:27:29 +00:00
|
|
|
byte code[] = {
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOOP(WASM_IF(WASM_LOCAL_GET(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
|
2016-01-25 10:27:29 +00:00
|
|
|
WASM_SET_ZERO(0)};
|
|
|
|
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
|
|
|
bool expected = j == 1;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 5;
|
2016-01-25 10:27:29 +00:00
|
|
|
byte code[] = {
|
2016-07-21 11:04:06 +00:00
|
|
|
WASM_LOOP(WASM_IF(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(0),
|
|
|
|
WASM_BRV(0, WASM_LOCAL_SET(3, WASM_I32_SUB(WASM_LOCAL_GET(0),
|
2017-01-09 13:57:26 +00:00
|
|
|
WASM_I32V_1(1)))))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(0)};
|
2016-01-25 10:27:29 +00:00
|
|
|
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
|
|
|
bool expected = j == 3;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
|
2016-03-07 21:04:07 +00:00
|
|
|
num_locals = 6;
|
2016-01-25 10:27:29 +00:00
|
|
|
const byte kIter = 0;
|
|
|
|
const byte kSum = 3;
|
|
|
|
|
|
|
|
byte code[] = {WASM_BLOCK(
|
|
|
|
WASM_WHILE(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(kIter),
|
2016-07-21 11:04:06 +00:00
|
|
|
WASM_BLOCK(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(
|
|
|
|
kSum, WASM_F32_ADD(WASM_LOCAL_GET(kSum),
|
2016-07-21 11:04:06 +00:00
|
|
|
WASM_LOAD_MEM(MachineType::Float32(),
|
2020-12-17 16:55:33 +00:00
|
|
|
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))};
|
2016-01-25 10:27:29 +00:00
|
|
|
|
2016-09-27 20:46:10 +00:00
|
|
|
BitVector* assigned = Analyze(code + 2, code + arraysize(code));
|
2016-01-25 10:27:29 +00:00
|
|
|
for (int j = 0; j < assigned->length(); j++) {
|
|
|
|
bool expected = j == kIter || j == kSum;
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(expected, assigned->Contains(j));
|
2016-01-25 10:27:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 20:35:30 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, Malformed) {
|
2020-09-29 07:46:36 +00:00
|
|
|
byte code[] = {kExprLoop, kVoidCode, kExprF32Neg, kExprBrTable, 0x0E, 'h',
|
|
|
|
'e', 'l', 'l', 'o', ',', ' ',
|
|
|
|
'w', 'o', 'r', 'l', 'd', '!'};
|
2016-06-27 20:35:30 +00:00
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
2020-12-03 11:53:34 +00:00
|
|
|
EXPECT_EQ(assigned, nullptr);
|
2016-06-27 20:35:30 +00:00
|
|
|
}
|
|
|
|
|
2020-11-24 11:33:55 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, InvalidOpcode) {
|
|
|
|
byte code[] = {WASM_LOOP(0xFF)};
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
EXPECT_EQ(assigned, nullptr);
|
|
|
|
}
|
|
|
|
|
2016-09-01 14:05:19 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, regress_642867) {
|
|
|
|
static const byte code[] = {
|
2019-10-08 12:38:48 +00:00
|
|
|
WASM_LOOP(WASM_ZERO, kExprLocalSet, 0xFA, 0xFF, 0xFF, 0xFF,
|
2017-12-02 00:30:37 +00:00
|
|
|
0x0F)}; // local index LEB128 0xFFFFFFFA
|
2016-09-01 14:05:19 +00:00
|
|
|
// Just make sure that the analysis does not crash.
|
|
|
|
Analyze(code, code + arraysize(code));
|
|
|
|
}
|
|
|
|
|
2020-12-03 11:53:34 +00:00
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, LetInLoopAssigned) {
|
|
|
|
num_locals = 5;
|
|
|
|
static const byte code[] = {
|
|
|
|
WASM_LOOP(WASM_LET_1_V(kI32Code, WASM_I32V_1(42), WASM_SET_ZERO(3)))};
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (uint32_t i = 0; i <= num_locals; i++) {
|
|
|
|
EXPECT_EQ(assigned->Contains(i), i == 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, LetInLoopNotAssigned) {
|
|
|
|
num_locals = 2;
|
|
|
|
static const byte code[] = {WASM_LOOP(
|
|
|
|
WASM_LET_1_V(kI32Code, WASM_I32V_1(42),
|
|
|
|
WASM_LET_1_V(kI32Code, WASM_I32V_1(42), WASM_SET_ZERO(0),
|
|
|
|
WASM_SET_ZERO(1))))};
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (uint32_t i = 0; i <= num_locals; i++) {
|
|
|
|
EXPECT_FALSE(assigned->Contains(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(WasmLoopAssignmentAnalyzerTest, AssignmentOutsideOfLet) {
|
|
|
|
num_locals = 5;
|
|
|
|
static const byte code[] = {
|
|
|
|
WASM_LOOP(WASM_LET_1_V(kI32Code, WASM_I32V_1(42), WASM_SET_ZERO(3)),
|
|
|
|
WASM_SET_ZERO(4))};
|
|
|
|
BitVector* assigned = Analyze(code, code + arraysize(code));
|
|
|
|
for (uint32_t i = 0; i <= num_locals; i++) {
|
|
|
|
EXPECT_EQ(assigned->Contains(i), i == 2 || i == 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-08 13:59:05 +00:00
|
|
|
#undef WASM_SET_ZERO
|
|
|
|
|
2016-01-25 10:27:29 +00:00
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|