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 <stdint.h> | 5 #include <stdint.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "src/wasm/wasm-macro-gen.h" | 9 #include "src/wasm/wasm-macro-gen.h" |
10 | 10 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 WASM_GET_LOCAL(0), | 128 WASM_GET_LOCAL(0), |
129 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)), | 129 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)), |
130 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14)))); | 130 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14)))); |
131 | 131 |
132 CHECK_EQ(11, r.Call(1, 1)); | 132 CHECK_EQ(11, r.Call(1, 1)); |
133 CHECK_EQ(12, r.Call(1, 0)); | 133 CHECK_EQ(12, r.Call(1, 0)); |
134 CHECK_EQ(13, r.Call(0, 1)); | 134 CHECK_EQ(13, r.Call(0, 1)); |
135 CHECK_EQ(14, r.Call(0, 0)); | 135 CHECK_EQ(14, r.Call(0, 0)); |
136 } | 136 } |
137 | 137 |
138 TEST(Step_I32Add) { | 138 // Make tests more robust by not hard-coding offsets of various operations. |
139 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32(), | 139 // The {Find} method finds the offsets for the given bytecodes, returning |
140 MachineType::Int32()); | 140 // the offsets in an array. |
141 BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); | 141 SmartArrayPointer<int> Find(byte* code, size_t code_size, int n, ...) { |
| 142 va_list vl; |
| 143 va_start(vl, n); |
| 144 |
| 145 SmartArrayPointer<int> offsets(new int[n]); |
| 146 |
| 147 for (int i = 0; i < n; i++) { |
| 148 offsets[i] = -1; |
| 149 } |
| 150 |
| 151 int pos = 0; |
| 152 WasmOpcode current = static_cast<WasmOpcode>(va_arg(vl, int)); |
| 153 for (size_t i = 0; i < code_size; i++) { |
| 154 if (code[i] == current) { |
| 155 offsets[pos++] = static_cast<int>(i); |
| 156 if (pos == n) break; |
| 157 current = static_cast<WasmOpcode>(va_arg(vl, int)); |
| 158 } |
| 159 } |
| 160 va_end(vl); |
| 161 |
| 162 return offsets; |
| 163 } |
| 164 |
| 165 TEST(Breakpoint_I32Add) { |
| 166 static const int kLocalsDeclSize = 1; |
| 167 static const int kNumBreakpoints = 3; |
| 168 byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; |
| 169 SmartArrayPointer<int> offsets = |
| 170 Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal, |
| 171 kExprI32Add); |
| 172 |
| 173 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), |
| 174 MachineType::Uint32()); |
| 175 |
| 176 r.Build(code, code + arraysize(code)); |
142 | 177 |
143 WasmInterpreter* interpreter = r.interpreter(); | 178 WasmInterpreter* interpreter = r.interpreter(); |
144 interpreter->SetBreakpoint(r.function(), 0, true); | 179 WasmInterpreter::Thread& thread = interpreter->GetThread(0); |
| 180 for (int i = 0; i < kNumBreakpoints; i++) { |
| 181 interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[i], |
| 182 true); |
| 183 } |
145 | 184 |
146 r.Call(1, 1); | 185 FOR_UINT32_INPUTS(a) { |
147 interpreter->Run(); | 186 for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) { |
148 CHECK_EQ(2, interpreter->GetThread(0).GetReturnValue().to<int32_t>()); | 187 thread.Reset(); |
| 188 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; |
| 189 thread.PushFrame(r.function(), args); |
| 190 |
| 191 for (int i = 0; i < kNumBreakpoints; i++) { |
| 192 thread.Run(); // run to next breakpoint |
| 193 // Check the thread stopped at the right pc. |
| 194 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); |
| 195 CHECK_EQ(kLocalsDeclSize + offsets[i], thread.GetBreakpointPc()); |
| 196 } |
| 197 |
| 198 thread.Run(); // run to completion |
| 199 |
| 200 // Check the thread finished with the right value. |
| 201 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); |
| 202 uint32_t expected = (*a) + (b); |
| 203 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); |
| 204 } |
| 205 } |
| 206 } |
| 207 |
| 208 TEST(Step_I32Mul) { |
| 209 static const int kTraceLength = 4; |
| 210 byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; |
| 211 |
| 212 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), |
| 213 MachineType::Uint32()); |
| 214 |
| 215 r.Build(code, code + arraysize(code)); |
| 216 |
| 217 WasmInterpreter* interpreter = r.interpreter(); |
| 218 WasmInterpreter::Thread& thread = interpreter->GetThread(0); |
| 219 |
| 220 FOR_UINT32_INPUTS(a) { |
| 221 for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) { |
| 222 thread.Reset(); |
| 223 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; |
| 224 thread.PushFrame(r.function(), args); |
| 225 |
| 226 // Run instructions one by one. |
| 227 for (int i = 0; i < kTraceLength - 1; i++) { |
| 228 thread.Step(); |
| 229 // Check the thread stopped. |
| 230 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); |
| 231 } |
| 232 |
| 233 // Run last instruction. |
| 234 thread.Step(); |
| 235 |
| 236 // Check the thread finished with the right value. |
| 237 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); |
| 238 uint32_t expected = (*a) * (b); |
| 239 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); |
| 240 } |
| 241 } |
| 242 } |
| 243 |
| 244 TEST(Breakpoint_I32And_disable) { |
| 245 static const int kLocalsDeclSize = 1; |
| 246 static const int kNumBreakpoints = 1; |
| 247 byte code[] = {WASM_I32_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; |
| 248 SmartArrayPointer<int> offsets = |
| 249 Find(code, sizeof(code), kNumBreakpoints, kExprI32And); |
| 250 |
| 251 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), |
| 252 MachineType::Uint32()); |
| 253 |
| 254 r.Build(code, code + arraysize(code)); |
| 255 |
| 256 WasmInterpreter* interpreter = r.interpreter(); |
| 257 WasmInterpreter::Thread& thread = interpreter->GetThread(0); |
| 258 |
| 259 FOR_UINT32_INPUTS(a) { |
| 260 for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) { |
| 261 // Run with and without breakpoints. |
| 262 for (int do_break = 0; do_break < 2; do_break++) { |
| 263 interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0], |
| 264 do_break); |
| 265 thread.Reset(); |
| 266 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; |
| 267 thread.PushFrame(r.function(), args); |
| 268 |
| 269 if (do_break) { |
| 270 thread.Run(); // run to next breakpoint |
| 271 // Check the thread stopped at the right pc. |
| 272 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); |
| 273 CHECK_EQ(kLocalsDeclSize + offsets[0], thread.GetBreakpointPc()); |
| 274 } |
| 275 |
| 276 thread.Run(); // run to completion |
| 277 |
| 278 // Check the thread finished with the right value. |
| 279 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); |
| 280 uint32_t expected = (*a) & (b); |
| 281 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); |
| 282 } |
| 283 } |
| 284 } |
149 } | 285 } |
150 | 286 |
151 } // namespace wasm | 287 } // namespace wasm |
152 } // namespace internal | 288 } // namespace internal |
153 } // namespace v8 | 289 } // namespace v8 |
OLD | NEW |