| 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 |