OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "test/unittests/test-utils.h" | 5 #include "test/unittests/test-utils.h" |
6 #include "testing/gmock/include/gmock/gmock.h" | 6 #include "testing/gmock/include/gmock/gmock.h" |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/wasm/wasm-interpreter.h" | 10 #include "src/wasm/wasm-interpreter.h" |
11 #include "src/wasm/wasm-macro-gen.h" | 11 #include "src/wasm/wasm-macro-gen.h" |
12 | 12 |
13 using testing::MakeMatcher; | 13 using testing::MakeMatcher; |
14 using testing::Matcher; | 14 using testing::Matcher; |
15 using testing::MatcherInterface; | 15 using testing::MatcherInterface; |
16 using testing::MatchResultListener; | 16 using testing::MatchResultListener; |
17 using testing::StringMatchResultListener; | 17 using testing::StringMatchResultListener; |
18 | 18 |
19 namespace v8 { | 19 namespace v8 { |
20 namespace internal { | 20 namespace internal { |
21 namespace wasm { | 21 namespace wasm { |
22 | 22 |
23 #define B1(a) kExprBlock, a, kExprEnd | 23 #define B1(a) kExprBlock, a, kExprEnd |
24 #define B2(a, b) kExprBlock, a, b, kExprEnd | 24 #define B2(a, b) kExprBlock, a, b, kExprEnd |
25 #define B3(a, b, c) kExprBlock, a, b, c, kExprEnd | 25 #define B3(a, b, c) kExprBlock, a, b, c, kExprEnd |
26 | 26 |
27 struct ExpectedTarget { | 27 #define TRANSFER_VOID 0 |
| 28 #define TRANSFER_ONE 1 |
| 29 |
| 30 struct ExpectedPcDelta { |
28 pc_t pc; | 31 pc_t pc; |
29 ControlTransfer expected; | 32 pcdiff_t expected; |
30 }; | 33 }; |
31 | 34 |
32 // For nicer error messages. | 35 // For nicer error messages. |
33 class ControlTransferMatcher : public MatcherInterface<const ControlTransfer&> { | 36 class ControlTransferMatcher : public MatcherInterface<const pcdiff_t&> { |
34 public: | 37 public: |
35 explicit ControlTransferMatcher(pc_t pc, const ControlTransfer& expected) | 38 explicit ControlTransferMatcher(pc_t pc, const pcdiff_t& expected) |
36 : pc_(pc), expected_(expected) {} | 39 : pc_(pc), expected_(expected) {} |
37 | 40 |
38 void DescribeTo(std::ostream* os) const override { | 41 void DescribeTo(std::ostream* os) const override { |
39 *os << "@" << pc_ << " {pcdiff = " << expected_.pcdiff | 42 *os << "@" << pc_ << " pcdiff = " << expected_; |
40 << ", spdiff = " << expected_.spdiff | |
41 << ", action = " << expected_.action << "}"; | |
42 } | 43 } |
43 | 44 |
44 bool MatchAndExplain(const ControlTransfer& input, | 45 bool MatchAndExplain(const pcdiff_t& input, |
45 MatchResultListener* listener) const override { | 46 MatchResultListener* listener) const override { |
46 if (input.pcdiff != expected_.pcdiff || input.spdiff != expected_.spdiff || | 47 if (input != expected_) { |
47 input.action != expected_.action) { | 48 *listener << "@" << pc_ << " pcdiff = " << input; |
48 *listener << "@" << pc_ << " {pcdiff = " << input.pcdiff | |
49 << ", spdiff = " << input.spdiff | |
50 << ", action = " << input.action << "}"; | |
51 return false; | 49 return false; |
52 } | 50 } |
53 return true; | 51 return true; |
54 } | 52 } |
55 | 53 |
56 private: | 54 private: |
57 pc_t pc_; | 55 pc_t pc_; |
58 const ControlTransfer& expected_; | 56 const pcdiff_t& expected_; |
59 }; | 57 }; |
60 | 58 |
61 class ControlTransferTest : public TestWithZone { | 59 class ControlTransferTest : public TestWithZone { |
62 public: | 60 public: |
63 void CheckControlTransfers(const byte* start, const byte* end, | 61 void CheckPcDeltas(const byte* start, const byte* end, |
64 ExpectedTarget* expected_targets, | 62 ExpectedPcDelta* expected_deltas, size_t num_targets) { |
65 size_t num_targets) { | |
66 ControlTransferMap map = | 63 ControlTransferMap map = |
67 WasmInterpreter::ComputeControlTransfersForTesting(zone(), start, end); | 64 WasmInterpreter::ComputeControlTransfersForTesting(zone(), start, end); |
68 // Check all control targets in the map. | 65 // Check all control targets in the map. |
69 for (size_t i = 0; i < num_targets; i++) { | 66 for (size_t i = 0; i < num_targets; i++) { |
70 pc_t pc = expected_targets[i].pc; | 67 pc_t pc = expected_deltas[i].pc; |
71 auto it = map.find(pc); | 68 auto it = map.find(pc); |
72 if (it == map.end()) { | 69 if (it == map.end()) { |
73 printf("expected control target @ +%zu\n", pc); | 70 EXPECT_TRUE(false) << "expected control target @ " << pc; |
74 EXPECT_TRUE(false); | |
75 } else { | 71 } else { |
76 ControlTransfer& expected = expected_targets[i].expected; | 72 pcdiff_t expected = expected_deltas[i].expected; |
77 ControlTransfer& target = it->second; | 73 pcdiff_t& target = it->second; |
78 EXPECT_THAT(target, | 74 EXPECT_THAT(target, |
79 MakeMatcher(new ControlTransferMatcher(pc, expected))); | 75 MakeMatcher(new ControlTransferMatcher(pc, expected))); |
80 } | 76 } |
81 } | 77 } |
82 | 78 |
83 // Check there are no other control targets. | 79 // Check there are no other control targets. |
| 80 CheckNoOtherTargets<ExpectedPcDelta>(start, end, map, expected_deltas, |
| 81 num_targets); |
| 82 } |
| 83 |
| 84 template <typename T> |
| 85 void CheckNoOtherTargets(const byte* start, const byte* end, |
| 86 ControlTransferMap& map, T* targets, |
| 87 size_t num_targets) { |
| 88 // Check there are no other control targets. |
84 for (pc_t pc = 0; start + pc < end; pc++) { | 89 for (pc_t pc = 0; start + pc < end; pc++) { |
85 bool found = false; | 90 bool found = false; |
86 for (size_t i = 0; i < num_targets; i++) { | 91 for (size_t i = 0; i < num_targets; i++) { |
87 if (expected_targets[i].pc == pc) { | 92 if (targets[i].pc == pc) { |
88 found = true; | 93 found = true; |
89 break; | 94 break; |
90 } | 95 } |
91 } | 96 } |
92 if (found) continue; | 97 if (found) continue; |
93 if (map.find(pc) != map.end()) { | 98 if (map.find(pc) != map.end()) { |
94 printf("expected no control @ +%zu\n", pc); | 99 printf("expected no control @ +%zu\n", pc); |
95 EXPECT_TRUE(false); | 100 EXPECT_TRUE(false); |
96 } | 101 } |
97 } | 102 } |
98 } | 103 } |
99 }; | 104 }; |
100 | 105 |
101 // Macro for simplifying tests below. | 106 #define EXPECT_PC_DELTAS(...) \ |
102 #define EXPECT_TARGETS(...) \ | 107 do { \ |
103 do { \ | 108 ExpectedPcDelta pairs[] = {__VA_ARGS__}; \ |
104 ExpectedTarget pairs[] = {__VA_ARGS__}; \ | 109 CheckPcDeltas(code, code + sizeof(code), pairs, arraysize(pairs)); \ |
105 CheckControlTransfers(code, code + sizeof(code), pairs, arraysize(pairs)); \ | |
106 } while (false) | 110 } while (false) |
107 | 111 |
108 TEST_F(ControlTransferTest, SimpleIf) { | 112 TEST_F(ControlTransferTest, SimpleIf) { |
109 byte code[] = { | 113 byte code[] = { |
110 kExprI32Const, // @0 | 114 kExprI32Const, // @0 |
111 0, // +1 | 115 0, // @1 |
112 kExprIf, // @2 | 116 kExprIf, // @2 |
113 kExprEnd // @3 | 117 kLocalVoid, // @3 |
| 118 kExprEnd // @4 |
114 }; | 119 }; |
115 EXPECT_TARGETS({2, {2, 0, ControlTransfer::kPushVoid}}, // -- | 120 EXPECT_PC_DELTAS({2, 2}); |
116 {3, {1, 0, ControlTransfer::kPushVoid}}); | |
117 } | 121 } |
118 | 122 |
119 TEST_F(ControlTransferTest, SimpleIf1) { | 123 TEST_F(ControlTransferTest, SimpleIf1) { |
120 byte code[] = { | 124 byte code[] = { |
121 kExprI32Const, // @0 | 125 kExprI32Const, // @0 |
122 0, // +1 | 126 0, // @1 |
123 kExprIf, // @2 | 127 kExprIf, // @2 |
124 kExprNop, // @3 | 128 kLocalVoid, // @3 |
125 kExprEnd // @4 | 129 kExprNop, // @4 |
| 130 kExprEnd // @5 |
126 }; | 131 }; |
127 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kPushVoid}}, // -- | 132 EXPECT_PC_DELTAS({2, 3}); |
128 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
129 } | 133 } |
130 | 134 |
131 TEST_F(ControlTransferTest, SimpleIf2) { | 135 TEST_F(ControlTransferTest, SimpleIf2) { |
132 byte code[] = { | 136 byte code[] = { |
133 kExprI32Const, // @0 | 137 kExprI32Const, // @0 |
134 0, // +1 | 138 0, // @1 |
135 kExprIf, // @2 | 139 kExprIf, // @2 |
136 kExprNop, // @3 | 140 kLocalVoid, // @3 |
137 kExprNop, // @4 | 141 kExprNop, // @4 |
138 kExprEnd // @5 | 142 kExprNop, // @5 |
| 143 kExprEnd // @6 |
139 }; | 144 }; |
140 EXPECT_TARGETS({2, {4, 0, ControlTransfer::kPushVoid}}, // -- | 145 EXPECT_PC_DELTAS({2, 4}); |
141 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
142 } | 146 } |
143 | 147 |
144 TEST_F(ControlTransferTest, SimpleIfElse) { | 148 TEST_F(ControlTransferTest, SimpleIfElse) { |
145 byte code[] = { | 149 byte code[] = { |
146 kExprI32Const, // @0 | 150 kExprI32Const, // @0 |
147 0, // +1 | 151 0, // @1 |
148 kExprIf, // @2 | 152 kExprIf, // @2 |
149 kExprElse, // @3 | 153 kLocalVoid, // @3 |
150 kExprEnd // @4 | 154 kExprElse, // @4 |
| 155 kExprEnd // @5 |
151 }; | 156 }; |
152 EXPECT_TARGETS({2, {2, 0, ControlTransfer::kNoAction}}, // -- | 157 EXPECT_PC_DELTAS({2, 3}, {4, 2}); |
153 {3, {2, 0, ControlTransfer::kPushVoid}}, // -- | 158 } |
154 {4, {1, 0, ControlTransfer::kPushVoid}}); | 159 |
| 160 TEST_F(ControlTransferTest, SimpleIfElse_v1) { |
| 161 byte code[] = { |
| 162 kExprI32Const, // @0 |
| 163 0, // @1 |
| 164 kExprIf, // @2 |
| 165 kLocalVoid, // @3 |
| 166 kExprI8Const, // @4 |
| 167 0, // @5 |
| 168 kExprElse, // @6 |
| 169 kExprI8Const, // @7 |
| 170 0, // @8 |
| 171 kExprEnd // @9 |
| 172 }; |
| 173 EXPECT_PC_DELTAS({2, 5}, {6, 4}); |
155 } | 174 } |
156 | 175 |
157 TEST_F(ControlTransferTest, SimpleIfElse1) { | 176 TEST_F(ControlTransferTest, SimpleIfElse1) { |
158 byte code[] = { | 177 byte code[] = { |
159 kExprI32Const, // @0 | 178 kExprI32Const, // @0 |
160 0, // +1 | 179 0, // @1 |
161 kExprIf, // @2 | 180 kExprIf, // @2 |
162 kExprNop, // @3 | 181 kLocalVoid, // @3 |
163 kExprElse, // @4 | 182 kExprElse, // @4 |
164 kExprNop, // @5 | 183 kExprNop, // @5 |
165 kExprEnd // @6 | 184 kExprEnd // @6 |
166 }; | 185 }; |
167 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}}, // -- | 186 EXPECT_PC_DELTAS({2, 3}, {4, 3}); |
168 {4, {3, 1, ControlTransfer::kPopAndRepush}}, // -- | |
169 {6, {1, 1, ControlTransfer::kPopAndRepush}}); | |
170 } | 187 } |
171 | 188 |
172 TEST_F(ControlTransferTest, IfBr) { | 189 TEST_F(ControlTransferTest, IfBr) { |
173 byte code[] = { | 190 byte code[] = { |
174 kExprI32Const, // @0 | 191 kExprI32Const, // @0 |
175 0, // +1 | 192 0, // @1 |
176 kExprIf, // @2 | 193 kExprIf, // @2 |
177 kExprBr, // @3 | 194 kLocalVoid, // @3 |
178 ARITY_0, // +1 | 195 kExprBr, // @4 |
179 0, // +1 | 196 0, // @5 |
180 kExprEnd // @6 | 197 kExprEnd // @6 |
181 }; | 198 }; |
182 EXPECT_TARGETS({2, {5, 0, ControlTransfer::kPushVoid}}, // -- | 199 EXPECT_PC_DELTAS({2, 4}, {4, 3}); |
183 {3, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
184 {6, {1, 1, ControlTransfer::kPopAndRepush}}); | |
185 } | 200 } |
186 | 201 |
187 TEST_F(ControlTransferTest, IfBrElse) { | 202 TEST_F(ControlTransferTest, IfBrElse) { |
188 byte code[] = { | 203 byte code[] = { |
189 kExprI32Const, // @0 | 204 kExprI32Const, // @0 |
190 0, // +1 | 205 0, // @1 |
191 kExprIf, // @2 | 206 kExprIf, // @2 |
192 kExprBr, // @3 | 207 kLocalVoid, // @3 |
193 ARITY_0, // +1 | 208 kExprBr, // @4 |
194 0, // +1 | 209 0, // @5 |
195 kExprElse, // @6 | 210 kExprElse, // @6 |
196 kExprEnd // @7 | 211 kExprEnd // @7 |
197 }; | 212 }; |
198 EXPECT_TARGETS({2, {5, 0, ControlTransfer::kNoAction}}, // -- | 213 EXPECT_PC_DELTAS({2, 5}, {4, 4}, {6, 2}); |
199 {3, {5, 0, ControlTransfer::kPushVoid}}, // -- | |
200 {6, {2, 1, ControlTransfer::kPopAndRepush}}, // -- | |
201 {7, {1, 0, ControlTransfer::kPushVoid}}); | |
202 } | 214 } |
203 | 215 |
204 TEST_F(ControlTransferTest, IfElseBr) { | 216 TEST_F(ControlTransferTest, IfElseBr) { |
205 byte code[] = { | 217 byte code[] = { |
206 kExprI32Const, // @0 | 218 kExprI32Const, // @0 |
207 0, // +1 | 219 0, // @1 |
208 kExprIf, // @2 | 220 kExprIf, // @2 |
209 kExprNop, // @3 | 221 kLocalVoid, // @3 |
210 kExprElse, // @4 | 222 kExprElse, // @4 |
211 kExprBr, // @5 | 223 kExprBr, // @5 |
212 ARITY_0, // +1 | 224 0, // @6 |
213 0, // +1 | 225 kExprEnd // @7 |
214 kExprEnd // @8 | |
215 }; | 226 }; |
216 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}}, // -- | 227 EXPECT_PC_DELTAS({2, 3}, {4, 4}, {5, 3}); |
217 {4, {5, 1, ControlTransfer::kPopAndRepush}}, // -- | |
218 {5, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
219 {8, {1, 1, ControlTransfer::kPopAndRepush}}); | |
220 } | 228 } |
221 | 229 |
222 TEST_F(ControlTransferTest, BlockEmpty) { | 230 TEST_F(ControlTransferTest, BlockEmpty) { |
223 byte code[] = { | 231 byte code[] = { |
224 kExprBlock, // @0 | 232 kExprBlock, // @0 |
225 kExprEnd // @1 | 233 kExprEnd // @1 |
226 }; | 234 }; |
227 EXPECT_TARGETS({1, {1, 0, ControlTransfer::kPushVoid}}); | 235 CheckPcDeltas(code, code + sizeof(code), nullptr, 0); |
228 } | 236 } |
229 | 237 |
230 TEST_F(ControlTransferTest, Br0) { | 238 TEST_F(ControlTransferTest, Br0) { |
231 byte code[] = { | 239 byte code[] = { |
232 kExprBlock, // @0 | 240 kExprBlock, // @0 |
233 kExprBr, // @1 | 241 kLocalVoid, // @1 |
234 ARITY_0, // +1 | 242 kExprBr, // @2 |
235 0, // +1 | 243 0, // @3 |
236 kExprEnd // @4 | 244 kExprEnd // @4 |
237 }; | 245 }; |
238 EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}}, | 246 EXPECT_PC_DELTAS({2, 3}); |
239 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
240 } | 247 } |
241 | 248 |
242 TEST_F(ControlTransferTest, Br1) { | 249 TEST_F(ControlTransferTest, Br1) { |
243 byte code[] = { | 250 byte code[] = { |
244 kExprBlock, // @0 | 251 kExprBlock, // @0 |
245 kExprNop, // @1 | 252 kLocalVoid, // @1 |
246 kExprBr, // @2 | 253 kExprNop, // @2 |
247 ARITY_0, // +1 | 254 kExprBr, // @3 |
248 0, // +1 | 255 0, // @4 |
249 kExprEnd // @5 | 256 kExprEnd // @5 |
250 }; | 257 }; |
251 EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}}, // -- | 258 EXPECT_PC_DELTAS({3, 3}); |
252 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | 259 } |
| 260 |
| 261 TEST_F(ControlTransferTest, Br_v1a) { |
| 262 byte code[] = { |
| 263 kExprBlock, // @0 |
| 264 kLocalVoid, // @1 |
| 265 kExprI8Const, // @2 |
| 266 0, // @3 |
| 267 kExprBr, // @4 |
| 268 0, // @5 |
| 269 kExprEnd // @6 |
| 270 }; |
| 271 EXPECT_PC_DELTAS({4, 3}); |
| 272 } |
| 273 |
| 274 TEST_F(ControlTransferTest, Br_v1b) { |
| 275 byte code[] = { |
| 276 kExprBlock, // @0 |
| 277 kLocalVoid, // @1 |
| 278 kExprI8Const, // @2 |
| 279 0, // @3 |
| 280 kExprBr, // @4 |
| 281 0, // @5 |
| 282 kExprEnd // @6 |
| 283 }; |
| 284 EXPECT_PC_DELTAS({4, 3}); |
| 285 } |
| 286 |
| 287 TEST_F(ControlTransferTest, Br_v1c) { |
| 288 byte code[] = { |
| 289 kExprI8Const, // @0 |
| 290 0, // @1 |
| 291 kExprBlock, // @2 |
| 292 kLocalVoid, // @3 |
| 293 kExprBr, // @4 |
| 294 0, // @5 |
| 295 kExprEnd // @6 |
| 296 }; |
| 297 EXPECT_PC_DELTAS({4, 3}); |
253 } | 298 } |
254 | 299 |
255 TEST_F(ControlTransferTest, Br2) { | 300 TEST_F(ControlTransferTest, Br2) { |
256 byte code[] = { | 301 byte code[] = { |
257 kExprBlock, // @0 | 302 kExprBlock, // @0 |
258 kExprNop, // @1 | 303 kLocalVoid, // @1 |
259 kExprNop, // @2 | 304 kExprNop, // @2 |
260 kExprBr, // @3 | 305 kExprNop, // @3 |
261 ARITY_0, // +1 | 306 kExprBr, // @4 |
262 0, // +1 | 307 0, // @5 |
263 kExprEnd // @6 | 308 kExprEnd // @6 |
264 }; | 309 }; |
265 EXPECT_TARGETS({3, {4, 2, ControlTransfer::kPopAndRepush}}, // -- | 310 EXPECT_PC_DELTAS({4, 3}); |
266 {6, {1, 3, ControlTransfer::kPopAndRepush}}); | |
267 } | 311 } |
268 | 312 |
269 TEST_F(ControlTransferTest, Br0b) { | 313 TEST_F(ControlTransferTest, Br0b) { |
270 byte code[] = { | 314 byte code[] = { |
271 kExprBlock, // @0 | 315 kExprBlock, // @0 |
272 kExprBr, // @1 | 316 kLocalVoid, // @1 |
273 ARITY_0, // +1 | 317 kExprBr, // @2 |
274 0, // +1 | 318 0, // @3 |
275 kExprNop, // @4 | 319 kExprNop, // @4 |
276 kExprEnd // @5 | 320 kExprEnd // @5 |
277 }; | 321 }; |
278 EXPECT_TARGETS({1, {5, 0, ControlTransfer::kPushVoid}}, // -- | 322 EXPECT_PC_DELTAS({2, 4}); |
279 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
280 } | 323 } |
281 | 324 |
282 TEST_F(ControlTransferTest, Br0c) { | 325 TEST_F(ControlTransferTest, Br0c) { |
283 byte code[] = { | 326 byte code[] = { |
284 kExprBlock, // @0 | 327 kExprBlock, // @0 |
285 kExprBr, // @1 | 328 kLocalVoid, // @1 |
286 ARITY_0, // +1 | 329 kExprBr, // @2 |
287 0, // +1 | 330 0, // @3 |
288 kExprNop, // @4 | 331 kExprNop, // @4 |
289 kExprNop, // @5 | 332 kExprNop, // @5 |
290 kExprEnd // @6 | 333 kExprEnd // @6 |
291 }; | 334 }; |
292 EXPECT_TARGETS({1, {6, 0, ControlTransfer::kPushVoid}}, // -- | 335 EXPECT_PC_DELTAS({2, 5}); |
293 {6, {1, 3, ControlTransfer::kPopAndRepush}}); | |
294 } | 336 } |
295 | 337 |
296 TEST_F(ControlTransferTest, SimpleLoop1) { | 338 TEST_F(ControlTransferTest, SimpleLoop1) { |
297 byte code[] = { | 339 byte code[] = { |
298 kExprLoop, // @0 | 340 kExprLoop, // @0 |
299 kExprBr, // @1 | 341 kLocalVoid, // @1 |
300 ARITY_0, // +1 | 342 kExprBr, // @2 |
301 0, // +1 | 343 0, // @3 |
302 kExprEnd // @4 | 344 kExprEnd // @4 |
303 }; | 345 }; |
304 EXPECT_TARGETS({1, {-1, 0, ControlTransfer::kNoAction}}, // -- | 346 EXPECT_PC_DELTAS({2, -2}); |
305 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
306 } | 347 } |
307 | 348 |
308 TEST_F(ControlTransferTest, SimpleLoop2) { | 349 TEST_F(ControlTransferTest, SimpleLoop2) { |
309 byte code[] = { | 350 byte code[] = { |
310 kExprLoop, // @0 | 351 kExprLoop, // @0 |
311 kExprNop, // @1 | 352 kLocalVoid, // @1 |
312 kExprBr, // @2 | 353 kExprNop, // @2 |
313 ARITY_0, // +1 | 354 kExprBr, // @3 |
314 0, // +1 | 355 0, // @4 |
315 kExprEnd // @5 | 356 kExprEnd // @5 |
316 }; | 357 }; |
317 EXPECT_TARGETS({2, {-2, 1, ControlTransfer::kNoAction}}, // -- | 358 EXPECT_PC_DELTAS({3, -3}); |
318 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
319 } | 359 } |
320 | 360 |
321 TEST_F(ControlTransferTest, SimpleLoopExit1) { | 361 TEST_F(ControlTransferTest, SimpleLoopExit1) { |
322 byte code[] = { | 362 byte code[] = { |
323 kExprLoop, // @0 | 363 kExprLoop, // @0 |
324 kExprBr, // @1 | 364 kLocalVoid, // @1 |
325 ARITY_0, // +1 | 365 kExprBr, // @2 |
326 1, // +1 | 366 1, // @3 |
327 kExprEnd // @4 | 367 kExprEnd // @4 |
328 }; | 368 }; |
329 EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}}, // -- | 369 EXPECT_PC_DELTAS({2, 3}); |
330 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
331 } | 370 } |
332 | 371 |
333 TEST_F(ControlTransferTest, SimpleLoopExit2) { | 372 TEST_F(ControlTransferTest, SimpleLoopExit2) { |
334 byte code[] = { | 373 byte code[] = { |
335 kExprLoop, // @0 | 374 kExprLoop, // @0 |
336 kExprNop, // @1 | 375 kLocalVoid, // @1 |
337 kExprBr, // @2 | 376 kExprNop, // @2 |
338 ARITY_0, // +1 | 377 kExprBr, // @3 |
339 1, // +1 | 378 1, // @4 |
340 kExprEnd // @5 | 379 kExprEnd // @5 |
341 }; | 380 }; |
342 EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}}, // -- | 381 EXPECT_PC_DELTAS({3, 3}); |
343 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
344 } | 382 } |
345 | 383 |
346 TEST_F(ControlTransferTest, BrTable0) { | 384 TEST_F(ControlTransferTest, BrTable0) { |
347 byte code[] = { | 385 byte code[] = { |
348 kExprBlock, // @0 | 386 kExprBlock, // @0 |
349 kExprI8Const, // @1 | 387 kLocalVoid, // @1 |
350 0, // +1 | 388 kExprI8Const, // @2 |
351 kExprBrTable, // @3 | 389 0, // @3 |
352 ARITY_0, // +1 | 390 kExprBrTable, // @4 |
353 0, // +1 | 391 0, // @5 |
354 U32_LE(0), // +4 | 392 U32V_1(0), // @6 |
355 kExprEnd // @10 | 393 kExprEnd // @7 |
356 }; | 394 }; |
357 EXPECT_TARGETS({3, {8, 0, ControlTransfer::kPushVoid}}, // -- | 395 EXPECT_PC_DELTAS({4, 4}); |
358 {10, {1, 1, ControlTransfer::kPopAndRepush}}); | 396 } |
| 397 |
| 398 TEST_F(ControlTransferTest, BrTable0_v1a) { |
| 399 byte code[] = { |
| 400 kExprBlock, // @0 |
| 401 kLocalVoid, // @1 |
| 402 kExprI8Const, // @2 |
| 403 0, // @3 |
| 404 kExprI8Const, // @4 |
| 405 0, // @5 |
| 406 kExprBrTable, // @6 |
| 407 0, // @7 |
| 408 U32V_1(0), // @8 |
| 409 kExprEnd // @9 |
| 410 }; |
| 411 EXPECT_PC_DELTAS({6, 4}); |
| 412 } |
| 413 |
| 414 TEST_F(ControlTransferTest, BrTable0_v1b) { |
| 415 byte code[] = { |
| 416 kExprBlock, // @0 |
| 417 kLocalVoid, // @1 |
| 418 kExprI8Const, // @2 |
| 419 0, // @3 |
| 420 kExprI8Const, // @4 |
| 421 0, // @5 |
| 422 kExprBrTable, // @6 |
| 423 0, // @7 |
| 424 U32V_1(0), // @8 |
| 425 kExprEnd // @9 |
| 426 }; |
| 427 EXPECT_PC_DELTAS({6, 4}); |
359 } | 428 } |
360 | 429 |
361 TEST_F(ControlTransferTest, BrTable1) { | 430 TEST_F(ControlTransferTest, BrTable1) { |
362 byte code[] = { | 431 byte code[] = { |
363 kExprBlock, // @0 | 432 kExprBlock, // @0 |
364 kExprI8Const, // @1 | 433 kLocalVoid, // @1 |
365 0, // +1 | 434 kExprI8Const, // @2 |
366 kExprBrTable, // @3 | 435 0, // @3 |
367 ARITY_0, // +1 | 436 kExprBrTable, // @4 |
368 1, // +1 | 437 1, // @5 |
369 U32_LE(0), // +4 | 438 U32V_1(0), // @6 |
370 U32_LE(0), // +4 | 439 U32V_1(0), // @7 |
371 kExprEnd // @14 | 440 kExprEnd // @8 |
372 }; | 441 }; |
373 EXPECT_TARGETS({3, {12, 0, ControlTransfer::kPushVoid}}, // -- | 442 EXPECT_PC_DELTAS({4, 5}, {5, 4}); |
374 {4, {11, 0, ControlTransfer::kPushVoid}}, // -- | |
375 {14, {1, 1, ControlTransfer::kPopAndRepush}}); | |
376 } | 443 } |
377 | 444 |
378 TEST_F(ControlTransferTest, BrTable2) { | 445 TEST_F(ControlTransferTest, BrTable2) { |
379 byte code[] = { | 446 byte code[] = { |
380 kExprBlock, // @0 | 447 kExprBlock, // @0 |
381 kExprBlock, // @1 | 448 kLocalVoid, // @1 |
382 kExprI8Const, // @2 | 449 kExprBlock, // @2 |
383 0, // +1 | 450 kLocalVoid, // @3 |
384 kExprBrTable, // @4 | 451 kExprI8Const, // @4 |
385 ARITY_0, // +1 | 452 0, // @5 |
386 2, // +1 | 453 kExprBrTable, // @6 |
387 U32_LE(0), // +4 | 454 2, // @7 |
388 U32_LE(0), // +4 | 455 U32V_1(0), // @8 |
389 U32_LE(1), // +4 | 456 U32V_1(0), // @9 |
390 kExprEnd, // @19 | 457 U32V_1(1), // @10 |
391 kExprEnd // @19 | 458 kExprEnd, // @11 |
392 }; | 459 kExprEnd // @12 |
393 EXPECT_TARGETS({4, {16, 0, ControlTransfer::kPushVoid}}, // -- | 460 }; |
394 {5, {15, 0, ControlTransfer::kPushVoid}}, // -- | 461 EXPECT_PC_DELTAS({6, 6}, {7, 5}, {8, 5}); |
395 {6, {15, 0, ControlTransfer::kPushVoid}}, // -- | |
396 {19, {1, 1, ControlTransfer::kPopAndRepush}}, // -- | |
397 {20, {1, 1, ControlTransfer::kPopAndRepush}}); | |
398 } | 462 } |
399 | 463 |
400 } // namespace wasm | 464 } // namespace wasm |
401 } // namespace internal | 465 } // namespace internal |
402 } // namespace v8 | 466 } // namespace v8 |
OLD | NEW |