OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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 <stdlib.h> | 5 #include <stdlib.h> |
6 #include <string.h> | 6 #include <string.h> |
7 | 7 |
8 #include "src/compiler/graph-visualizer.h" | 8 #include "src/compiler/graph-visualizer.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/wasm-compiler.h" | 10 #include "src/compiler/wasm-compiler.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 | 25 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 |
26 #define WASM_64 1 | 26 #define WASM_64 1 |
27 #else | 27 #else |
28 #define WASM_64 0 | 28 #define WASM_64 0 |
29 #endif | 29 #endif |
30 | 30 |
31 // TODO(titzer): check traps more robustly in tests. | 31 // TODO(titzer): check traps more robustly in tests. |
32 // Currently, in tests, we just return 0xdeadbeef from the function in which | 32 // Currently, in tests, we just return 0xdeadbeef from the function in which |
33 // the trap occurs if the runtime context is not available to throw a JavaScript | 33 // the trap occurs if the runtime context is not available to throw a JavaScript |
34 // exception. | 34 // exception. |
35 #define CHECK_TRAP(x) CHECK_EQ(0xdeadbeef, (x)&0xFFFFFFFF) | 35 #define CHECK_TRAP32(x) \ |
| 36 CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF) |
| 37 #define CHECK_TRAP64(x) \ |
| 38 CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF) |
| 39 #define CHECK_TRAP(x) CHECK_TRAP32(x) |
| 40 |
36 | 41 |
37 using namespace v8::base; | 42 using namespace v8::base; |
38 using namespace v8::internal; | 43 using namespace v8::internal; |
39 using namespace v8::internal::compiler; | 44 using namespace v8::internal::compiler; |
40 using namespace v8::internal::wasm; | 45 using namespace v8::internal::wasm; |
41 | 46 |
42 static void init_env(FunctionEnv* env, FunctionSig* sig) { | 47 static void init_env(FunctionEnv* env, FunctionSig* sig) { |
43 env->module = nullptr; | 48 env->module = nullptr; |
44 env->sig = sig; | 49 env->sig = sig; |
45 env->local_int32_count = 0; | 50 env->local_int32_count = 0; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 CallDescriptor* descriptor_; | 212 CallDescriptor* descriptor_; |
208 | 213 |
209 Isolate* isolate() { return main_isolate(); } | 214 Isolate* isolate() { return main_isolate(); } |
210 Graph* graph() const { return main_graph_; } | 215 Graph* graph() const { return main_graph_; } |
211 Zone* zone() const { return graph()->zone(); } | 216 Zone* zone() const { return graph()->zone(); } |
212 CommonOperatorBuilder* common() { return &main_common_; } | 217 CommonOperatorBuilder* common() { return &main_common_; } |
213 MachineOperatorBuilder* machine() { return &main_machine_; } | 218 MachineOperatorBuilder* machine() { return &main_machine_; } |
214 CallDescriptor* descriptor() { return descriptor_; } | 219 CallDescriptor* descriptor() { return descriptor_; } |
215 | 220 |
216 void Build(const byte* start, const byte* end) { | 221 void Build(const byte* start, const byte* end) { |
217 compiler::WasmGraphBuilder builder(main_zone(), &jsgraph); | 222 compiler::WasmGraphBuilder builder(main_zone(), &jsgraph, env.sig); |
218 TreeResult result = BuildTFGraph(&builder, &env, start, end); | 223 TreeResult result = BuildTFGraph(&builder, &env, start, end); |
219 if (result.failed()) { | 224 if (result.failed()) { |
220 ptrdiff_t pc = result.error_pc - result.start; | 225 ptrdiff_t pc = result.error_pc - result.start; |
221 ptrdiff_t pt = result.error_pt - result.start; | 226 ptrdiff_t pt = result.error_pt - result.start; |
222 std::ostringstream str; | 227 std::ostringstream str; |
223 str << "Verification failed: " << result.error_code << " pc = +" << pc; | 228 str << "Verification failed: " << result.error_code << " pc = +" << pc; |
224 if (result.error_pt) str << ", pt = +" << pt; | 229 if (result.error_pt) str << ", pt = +" << pt; |
225 str << ", msg = " << result.error_msg.get(); | 230 str << ", msg = " << result.error_msg.get(); |
226 FATAL(str.str().c_str()); | 231 FATAL(str.str().c_str()); |
227 } | 232 } |
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 CHECK_TRAP(r.Call(0, 0)); | 971 CHECK_TRAP(r.Call(0, 0)); |
967 } | 972 } |
968 | 973 |
969 | 974 |
970 #if WASM_64 | 975 #if WASM_64 |
971 #define as64(x) static_cast<int64_t>(x) | 976 #define as64(x) static_cast<int64_t>(x) |
972 TEST(Run_WASM_Int64DivS_trap) { | 977 TEST(Run_WASM_Int64DivS_trap) { |
973 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 978 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
974 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 979 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
975 CHECK_EQ(0, r.Call(as64(0), as64(100))); | 980 CHECK_EQ(0, r.Call(as64(0), as64(100))); |
976 CHECK_TRAP(r.Call(as64(100), as64(0))); | 981 CHECK_TRAP64(r.Call(as64(100), as64(0))); |
977 CHECK_TRAP(r.Call(as64(-1001), as64(0))); | 982 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); |
978 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | 983 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); |
979 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | 984 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); |
980 } | 985 } |
981 | 986 |
982 | 987 |
983 TEST(Run_WASM_Int64RemS_trap) { | 988 TEST(Run_WASM_Int64RemS_trap) { |
984 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 989 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
985 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 990 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
986 CHECK_EQ(33, r.Call(as64(133), as64(100))); | 991 CHECK_EQ(33, r.Call(as64(133), as64(100))); |
987 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | 992 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); |
988 CHECK_TRAP(r.Call(as64(100), as64(0))); | 993 CHECK_TRAP64(r.Call(as64(100), as64(0))); |
989 CHECK_TRAP(r.Call(as64(-1001), as64(0))); | 994 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); |
990 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | 995 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); |
991 } | 996 } |
992 | 997 |
993 | 998 |
994 TEST(Run_WASM_Int64DivU_trap) { | 999 TEST(Run_WASM_Int64DivU_trap) { |
995 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 1000 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
996 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 1001 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
997 CHECK_EQ(0, r.Call(as64(0), as64(100))); | 1002 CHECK_EQ(0, r.Call(as64(0), as64(100))); |
998 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | 1003 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); |
999 CHECK_TRAP(r.Call(as64(100), as64(0))); | 1004 CHECK_TRAP64(r.Call(as64(100), as64(0))); |
1000 CHECK_TRAP(r.Call(as64(-1001), as64(0))); | 1005 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); |
1001 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | 1006 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); |
1002 } | 1007 } |
1003 | 1008 |
1004 | 1009 |
1005 TEST(Run_WASM_Int64RemU_trap) { | 1010 TEST(Run_WASM_Int64RemU_trap) { |
1006 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); | 1011 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); |
1007 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 1012 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
1008 CHECK_EQ(17, r.Call(as64(217), as64(100))); | 1013 CHECK_EQ(17, r.Call(as64(217), as64(100))); |
1009 CHECK_TRAP(r.Call(as64(100), as64(0))); | 1014 CHECK_TRAP64(r.Call(as64(100), as64(0))); |
1010 CHECK_TRAP(r.Call(as64(-1001), as64(0))); | 1015 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); |
1011 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); | 1016 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); |
1012 CHECK_EQ(std::numeric_limits<int64_t>::min(), | 1017 CHECK_EQ(std::numeric_limits<int64_t>::min(), |
1013 r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); | 1018 r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); |
1014 } | 1019 } |
1015 | 1020 |
1016 | 1021 |
1017 TEST(Run_WASM_Int64DivS_byzero_const) { | 1022 TEST(Run_WASM_Int64DivS_byzero_const) { |
1018 for (int8_t denom = -2; denom < 8; denom++) { | 1023 for (int8_t denom = -2; denom < 8; denom++) { |
1019 WasmRunner<int64_t> r(MachineType::Int64()); | 1024 WasmRunner<int64_t> r(MachineType::Int64()); |
1020 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64(denom))); | 1025 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64(denom))); |
1021 for (int64_t val = -7; val < 8; val++) { | 1026 for (int64_t val = -7; val < 8; val++) { |
1022 if (denom == 0) { | 1027 if (denom == 0) { |
1023 CHECK_TRAP(r.Call(val)); | 1028 CHECK_TRAP64(r.Call(val)); |
1024 } else { | 1029 } else { |
1025 CHECK_EQ(val / denom, r.Call(val)); | 1030 CHECK_EQ(val / denom, r.Call(val)); |
1026 } | 1031 } |
1027 } | 1032 } |
1028 } | 1033 } |
1029 } | 1034 } |
1030 | 1035 |
1031 | 1036 |
1032 TEST(Run_WASM_Int64DivU_byzero_const) { | 1037 TEST(Run_WASM_Int64DivU_byzero_const) { |
1033 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { | 1038 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { |
1034 WasmRunner<uint64_t> r(MachineType::Uint64()); | 1039 WasmRunner<uint64_t> r(MachineType::Uint64()); |
1035 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64(denom))); | 1040 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64(denom))); |
1036 | 1041 |
1037 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { | 1042 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { |
1038 if (denom == 0) { | 1043 if (denom == 0) { |
1039 CHECK_TRAP(r.Call(val)); | 1044 CHECK_TRAP64(r.Call(val)); |
1040 } else { | 1045 } else { |
1041 CHECK_EQ(val / denom, r.Call(val)); | 1046 CHECK_EQ(val / denom, r.Call(val)); |
1042 } | 1047 } |
1043 } | 1048 } |
1044 } | 1049 } |
1045 } | 1050 } |
1046 #endif | 1051 #endif |
1047 | 1052 |
1048 | 1053 |
1049 void TestFloat32Binop(WasmOpcode opcode, int32_t expected, float a, float b) { | 1054 void TestFloat32Binop(WasmOpcode opcode, int32_t expected, float a, float b) { |
(...skipping 2186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3236 } | 3241 } |
3237 | 3242 |
3238 | 3243 |
3239 TEST(Run_Wasm_F64UConvertI64) { | 3244 TEST(Run_Wasm_F64UConvertI64) { |
3240 WasmRunner<double> r(MachineType::Uint64()); | 3245 WasmRunner<double> r(MachineType::Uint64()); |
3241 BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0))); | 3246 BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0))); |
3242 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); } | 3247 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); } |
3243 } | 3248 } |
3244 | 3249 |
3245 | 3250 |
| 3251 TEST(Run_Wasm_I64SConvertF32) { |
| 3252 WasmRunner<int64_t> r(MachineType::Float32()); |
| 3253 BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0))); |
| 3254 |
| 3255 FOR_FLOAT32_INPUTS(i) { |
| 3256 if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) { |
| 3257 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); |
| 3258 } else { |
| 3259 CHECK_TRAP64(r.Call(*i)); |
| 3260 } |
| 3261 } |
| 3262 } |
| 3263 |
| 3264 |
| 3265 TEST(Run_Wasm_I64SConvertF64) { |
| 3266 WasmRunner<int64_t> r(MachineType::Float64()); |
| 3267 BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))); |
| 3268 |
| 3269 FOR_FLOAT64_INPUTS(i) { |
| 3270 if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) { |
| 3271 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); |
| 3272 } else { |
| 3273 CHECK_TRAP64(r.Call(*i)); |
| 3274 } |
| 3275 } |
| 3276 } |
| 3277 |
| 3278 |
| 3279 TEST(Run_Wasm_I64UConvertF32) { |
| 3280 WasmRunner<uint64_t> r(MachineType::Float32()); |
| 3281 BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0))); |
| 3282 |
| 3283 FOR_FLOAT32_INPUTS(i) { |
| 3284 if (*i < 18446744073709551616.0 && *i >= 0) { |
| 3285 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); |
| 3286 } else { |
| 3287 CHECK_TRAP64(r.Call(*i)); |
| 3288 } |
| 3289 } |
| 3290 } |
| 3291 |
| 3292 |
| 3293 TEST(Run_Wasm_I64UConvertF64) { |
| 3294 WasmRunner<uint64_t> r(MachineType::Float64()); |
| 3295 BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0))); |
| 3296 |
| 3297 FOR_FLOAT64_INPUTS(i) { |
| 3298 if (*i < 18446744073709551616.0 && *i >= 0) { |
| 3299 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); |
| 3300 } else { |
| 3301 CHECK_TRAP64(r.Call(*i)); |
| 3302 } |
| 3303 } |
| 3304 } |
3246 #endif | 3305 #endif |
3247 | 3306 |
3248 | 3307 |
3249 TEST(Run_Wasm_F64CopySign) { | 3308 TEST(Run_Wasm_F64CopySign) { |
3250 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64()); | 3309 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64()); |
3251 BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 3310 BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
3252 | 3311 |
3253 FOR_FLOAT64_INPUTS(i) { | 3312 FOR_FLOAT64_INPUTS(i) { |
3254 FOR_FLOAT64_INPUTS(j) { CheckDoubleEq(copysign(*i, *j), r.Call(*i, *j)); } | 3313 FOR_FLOAT64_INPUTS(j) { CheckDoubleEq(copysign(*i, *j), r.Call(*i, *j)); } |
3255 } | 3314 } |
3256 } | 3315 } |
3257 | 3316 |
3258 | 3317 |
3259 TEST(Run_Wasm_F32CopySign) { | 3318 TEST(Run_Wasm_F32CopySign) { |
3260 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); | 3319 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); |
3261 BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 3320 BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); |
3262 | 3321 |
3263 FOR_FLOAT32_INPUTS(i) { | 3322 FOR_FLOAT32_INPUTS(i) { |
3264 FOR_FLOAT32_INPUTS(j) { CheckFloatEq(copysign(*i, *j), r.Call(*i, *j)); } | 3323 FOR_FLOAT32_INPUTS(j) { CheckFloatEq(copysign(*i, *j), r.Call(*i, *j)); } |
3265 } | 3324 } |
3266 } | 3325 } |
OLD | NEW |