| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <stdint.h> | |
| 6 #include <stdlib.h> | |
| 7 #include <string.h> | |
| 8 | |
| 9 #include "src/base/platform/elapsed-timer.h" | |
| 10 | |
| 11 #include "src/wasm/wasm-macro-gen.h" | |
| 12 | |
| 13 #include "test/cctest/cctest.h" | |
| 14 #include "test/cctest/compiler/value-helper.h" | |
| 15 #include "test/cctest/wasm/test-signatures.h" | |
| 16 #include "test/cctest/wasm/wasm-run-utils.h" | |
| 17 | |
| 18 using namespace v8::base; | |
| 19 using namespace v8::internal; | |
| 20 using namespace v8::internal::compiler; | |
| 21 using namespace v8::internal::wasm; | |
| 22 | |
| 23 // TODO(jpp): WASM_EXEC_TEST(TryCatch) | |
| 24 | |
| 25 // TODO(jpp): Move these macros to src/wasm/wasm-macro-gen.h once zero cost | |
| 26 // exceptions are added to the spec. | |
| 27 #define WASM_TRY_FINALLY(...) kExprTryFinally, __VA_ARGS__, kExprEnd | |
| 28 #define WASM_FINALLY(...) kExprFinally, __VA_ARGS__ | |
| 29 | |
| 30 WASM_EXEC_TEST(TryFinally_single) { | |
| 31 if (execution_mode == kExecuteInterpreted) { | |
| 32 // TODO(jpp): implement eh support in the interpreter. | |
| 33 return; | |
| 34 } | |
| 35 | |
| 36 FLAG_wasm_eh_prototype = true; | |
| 37 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), | |
| 38 MachineType::Int32()); | |
| 39 // r(i32 p, i32 q) -> i32 { | |
| 40 // try { | |
| 41 // if (q) { | |
| 42 // break; | |
| 43 // } | |
| 44 // p += 0x0f0; | |
| 45 // } finally { | |
| 46 // p += 0x00f; | |
| 47 // } | |
| 48 // p += 0xf00 | |
| 49 // return p; | |
| 50 // } | |
| 51 BUILD(r, WASM_TRY_FINALLY( | |
| 52 WASM_IF(WASM_GET_LOCAL(1), WASM_BREAK(0)), | |
| 53 WASM_SET_LOCAL( | |
| 54 0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V_2(0xf0))), | |
| 55 WASM_FINALLY(WASM_SET_LOCAL( | |
| 56 0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V_1(0x0f))))), | |
| 57 WASM_SET_LOCAL(0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V(0xf00))), | |
| 58 WASM_GET_LOCAL(0)); | |
| 59 | |
| 60 CHECK_EQ(0xFFFF, r.Call(0xF000, 0)); | |
| 61 CHECK_EQ(0xFF0F, r.Call(0xF000, 1)); | |
| 62 } | |
| 63 | |
| 64 WASM_EXEC_TEST(TryFinally_double) { | |
| 65 if (execution_mode == kExecuteInterpreted) { | |
| 66 // TODO(jpp): implement eh support in the interpreter. | |
| 67 return; | |
| 68 } | |
| 69 | |
| 70 FLAG_wasm_eh_prototype = true; | |
| 71 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), | |
| 72 MachineType::Int32()); | |
| 73 // r(i32 p, i32 q) -> i32 { | |
| 74 // a: try { | |
| 75 // b: try { | |
| 76 // if (q == 40) { | |
| 77 // break a; | |
| 78 // } else { | |
| 79 // if (q == 1) { | |
| 80 // break b; | |
| 81 // } | |
| 82 // } | |
| 83 // p += 0x00000f; | |
| 84 // } finally { | |
| 85 // p += 0x0000f0; | |
| 86 // } | |
| 87 // p += 0x000f00; | |
| 88 // } finally { | |
| 89 // p += 0x00f000; | |
| 90 // } | |
| 91 // return p; | |
| 92 // } | |
| 93 BUILD( | |
| 94 r, | |
| 95 WASM_TRY_FINALLY( | |
| 96 WASM_TRY_FINALLY( | |
| 97 WASM_IF_ELSE(WASM_I32_EQ(WASM_GET_LOCAL(1), WASM_I32V(40)), | |
| 98 WASM_BREAK(1), | |
| 99 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(1), WASM_I32V(1)), | |
| 100 WASM_BREAK(1))), | |
| 101 WASM_SET_LOCAL( | |
| 102 0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V(0x00000f))), | |
| 103 WASM_FINALLY(WASM_SET_LOCAL( | |
| 104 0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V(0x0000f0))))), | |
| 105 WASM_SET_LOCAL(0, | |
| 106 WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V(0x000f00))), | |
| 107 WASM_FINALLY(WASM_SET_LOCAL( | |
| 108 0, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_I32V(0x00f000))))), | |
| 109 WASM_GET_LOCAL(0)); | |
| 110 | |
| 111 CHECK_EQ(0x7000ffff, r.Call(0x70000000, 2)); | |
| 112 CHECK_EQ(0x7000fff0, r.Call(0x70000000, 1)); | |
| 113 CHECK_EQ(0x7000f0f0, r.Call(0x70000000, 40)); | |
| 114 } | |
| 115 | |
| 116 WASM_EXEC_TEST(TryFinally_multiple) { | |
| 117 if (execution_mode == kExecuteInterpreted) { | |
| 118 // TODO(jpp): implement eh support in the interpreter. | |
| 119 return; | |
| 120 } | |
| 121 | |
| 122 FLAG_wasm_eh_prototype = true; | |
| 123 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), | |
| 124 MachineType::Int32()); | |
| 125 | |
| 126 // Handy-dandy shortcuts for recurring patterns for this test. | |
| 127 #define I32_IOR_LOCAL(local, value) \ | |
| 128 WASM_SET_LOCAL(local, WASM_I32_IOR(WASM_GET_LOCAL(local), WASM_I32V(value))) | |
| 129 #define IF_LOCAL_IS_BREAK_TO(local, value, depth) \ | |
| 130 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(local), WASM_I32V(value)), \ | |
| 131 WASM_BREAK(depth)) | |
| 132 | |
| 133 // r(i32 p, i32 q) -> i32 { | |
| 134 // a: try { | |
| 135 // b: try { | |
| 136 // c: try { | |
| 137 // d: try { | |
| 138 // e: try { | |
| 139 // switch (q) { | |
| 140 // case 1: break e; | |
| 141 // case 2: break d; | |
| 142 // case 3: break c; | |
| 143 // case 4: break b; | |
| 144 // case 5: break a; | |
| 145 // } | |
| 146 // p |= 0x00000001; | |
| 147 // } finally { | |
| 148 // p |= 0x00000002; | |
| 149 // } | |
| 150 // switch (q) { | |
| 151 // case 6: break d; | |
| 152 // case 7: break c; | |
| 153 // case 8: break b; | |
| 154 // case 9: break a; | |
| 155 // } | |
| 156 // p |= 0x00000004; | |
| 157 // } finally { | |
| 158 // p |= 0x00000008; | |
| 159 // } | |
| 160 // switch (q) { | |
| 161 // case 10: break c; | |
| 162 // case 11: break b; | |
| 163 // case 12: break a; | |
| 164 // } | |
| 165 // p |= 0x00000010; | |
| 166 // } finally { | |
| 167 // p |= 0x00000020; | |
| 168 // } | |
| 169 // switch (q) { | |
| 170 // case 13: break b; | |
| 171 // case 14: break a; | |
| 172 // } | |
| 173 // p |= 0x00000040; | |
| 174 // } finally { | |
| 175 // p |= 0x00000080; | |
| 176 // } | |
| 177 // switch (q) { | |
| 178 // case 15: break a; | |
| 179 // } | |
| 180 // p |= 0x00000100; | |
| 181 // } finally { | |
| 182 // p |= 0x00000200; | |
| 183 // } | |
| 184 // return p; | |
| 185 // } | |
| 186 BUILD( | |
| 187 r, | |
| 188 WASM_TRY_FINALLY( | |
| 189 WASM_TRY_FINALLY( | |
| 190 WASM_TRY_FINALLY( | |
| 191 WASM_TRY_FINALLY( | |
| 192 WASM_TRY_FINALLY( | |
| 193 IF_LOCAL_IS_BREAK_TO(1, 1, 0), | |
| 194 IF_LOCAL_IS_BREAK_TO(1, 2, 1), | |
| 195 IF_LOCAL_IS_BREAK_TO(1, 3, 2), | |
| 196 IF_LOCAL_IS_BREAK_TO(1, 4, 3), | |
| 197 IF_LOCAL_IS_BREAK_TO(1, 5, 4), | |
| 198 I32_IOR_LOCAL(0, 0x00000001), | |
| 199 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000002))), | |
| 200 IF_LOCAL_IS_BREAK_TO(1, 6, 0), | |
| 201 IF_LOCAL_IS_BREAK_TO(1, 7, 1), | |
| 202 IF_LOCAL_IS_BREAK_TO(1, 8, 2), | |
| 203 IF_LOCAL_IS_BREAK_TO(1, 9, 3), | |
| 204 I32_IOR_LOCAL(0, 0x00000004), | |
| 205 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000008))), | |
| 206 IF_LOCAL_IS_BREAK_TO(1, 10, 0), | |
| 207 IF_LOCAL_IS_BREAK_TO(1, 11, 1), | |
| 208 IF_LOCAL_IS_BREAK_TO(1, 12, 2), I32_IOR_LOCAL(0, 0x00000010), | |
| 209 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000020))), | |
| 210 IF_LOCAL_IS_BREAK_TO(1, 13, 0), IF_LOCAL_IS_BREAK_TO(1, 14, 1), | |
| 211 I32_IOR_LOCAL(0, 0x00000040), | |
| 212 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000080))), | |
| 213 IF_LOCAL_IS_BREAK_TO(1, 15, 0), I32_IOR_LOCAL(0, 0x00000100), | |
| 214 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000200))), | |
| 215 WASM_GET_LOCAL(0)); | |
| 216 #undef WASM_IF_LOCAL_IS_BREAK_TO | |
| 217 #undef WASM_I32_IOR_LOCAL | |
| 218 | |
| 219 const struct { | |
| 220 uint32_t inputs[2]; | |
| 221 uint32_t expected_output; | |
| 222 } kTests[] = { | |
| 223 {{0x80000000u, 0}, 0x800003ffu}, {{0x80000000u, 1}, 0x800003feu}, | |
| 224 {{0x80000000u, 2}, 0x800003fau}, {{0x80000000u, 3}, 0x800003eau}, | |
| 225 {{0x80000000u, 4}, 0x800003aau}, {{0x80000000u, 5}, 0x800002aau}, | |
| 226 {{0x80000000u, 6}, 0x800003fbu}, {{0x80000000u, 7}, 0x800003ebu}, | |
| 227 {{0x80000000u, 8}, 0x800003abu}, {{0x80000000u, 9}, 0x800002abu}, | |
| 228 {{0x80000000u, 10}, 0x800003efu}, {{0x80000000u, 11}, 0x800003afu}, | |
| 229 {{0x80000000u, 12}, 0x800002afu}, {{0x80000000u, 13}, 0x800003bfu}, | |
| 230 {{0x80000000u, 14}, 0x800002bfu}, {{0x80000000u, 15}, 0x800002ffu}, | |
| 231 }; | |
| 232 | |
| 233 for (uint32_t ii = 0; ii < arraysize(kTests); ++ii) { | |
| 234 const auto& test_instance = kTests[ii]; | |
| 235 CHECK_EQ(test_instance.expected_output, | |
| 236 static_cast<uint32_t>( | |
| 237 r.Call(test_instance.inputs[0], test_instance.inputs[1]))); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 WASM_EXEC_TEST(TryFinally_break_within_finally) { | |
| 242 if (execution_mode == kExecuteInterpreted) { | |
| 243 // TODO(jpp): implement eh support in the interpreter. | |
| 244 return; | |
| 245 } | |
| 246 | |
| 247 FLAG_wasm_eh_prototype = true; | |
| 248 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), | |
| 249 MachineType::Int32()); | |
| 250 | |
| 251 #define I32_IOR_LOCAL(local, value) \ | |
| 252 WASM_SET_LOCAL(local, WASM_I32_IOR(WASM_GET_LOCAL(local), WASM_I32V(value))) | |
| 253 #define IF_LOCAL_IS_BREAK_TO(local, value, depth) \ | |
| 254 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(local), WASM_I32V(value)), \ | |
| 255 WASM_BREAK(depth)) | |
| 256 | |
| 257 // r(i32 p, i32 q) -> i32 { | |
| 258 // a: try { | |
| 259 // } finally { | |
| 260 // b: try { | |
| 261 // c: try { | |
| 262 // } finally { | |
| 263 // d: try { | |
| 264 // e: try { | |
| 265 // } finally { | |
| 266 // f: try { | |
| 267 // } finally { | |
| 268 // if (q == 1) { | |
| 269 // break a; | |
| 270 // } | |
| 271 // p |= 0x00000001 | |
| 272 // } | |
| 273 // p |= 0x00000002 | |
| 274 // } | |
| 275 // p |= 0x00000004 | |
| 276 // } finally { | |
| 277 // p |= 0x00000008 /* should run */ | |
| 278 // } | |
| 279 // p |= 0x00000010 | |
| 280 // } | |
| 281 // p |= 0x00000020 | |
| 282 // } finally { | |
| 283 // p |= 0x00000040 /* should run */ | |
| 284 // } | |
| 285 // p |= 0x00000080 | |
| 286 // } | |
| 287 // return p; | |
| 288 // } | |
| 289 BUILD(r, | |
| 290 WASM_TRY_FINALLY( // a | |
| 291 WASM_FINALLY( | |
| 292 WASM_TRY_FINALLY( // b | |
| 293 WASM_TRY_FINALLY( // c | |
| 294 WASM_FINALLY( | |
| 295 WASM_TRY_FINALLY( // d | |
| 296 WASM_TRY_FINALLY( // e | |
| 297 WASM_FINALLY( | |
| 298 WASM_TRY_FINALLY( // f | |
| 299 WASM_FINALLY( | |
| 300 IF_LOCAL_IS_BREAK_TO(1, 1, 5), | |
| 301 I32_IOR_LOCAL(0, 0x00000001))), | |
| 302 I32_IOR_LOCAL(0, 0x00000002))), | |
| 303 I32_IOR_LOCAL(0, 0x00000004), | |
| 304 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000008))), | |
| 305 I32_IOR_LOCAL(0, 0x00000010))), | |
| 306 I32_IOR_LOCAL(0, 0x00000020), | |
| 307 WASM_FINALLY(I32_IOR_LOCAL(0, 0x00000040))), | |
| 308 I32_IOR_LOCAL(0, 0x00000080))), | |
| 309 WASM_GET_LOCAL(0)); | |
| 310 | |
| 311 #undef WASM_IF_LOCAL_IS_BREAK_TO | |
| 312 #undef WASM_I32_IOR_LOCAL | |
| 313 | |
| 314 CHECK_EQ(0x40000048, r.Call(0x40000000, 1)); | |
| 315 } | |
| 316 | |
| 317 // TODO(jpp): WASM_EXEC_TEST(TryCatchFinally) | |
| OLD | NEW |