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 int* raw = new int[n]; | |
146 SmartArrayPointer<int> offsets(raw); | |
ahaas
2016/05/30 08:19:31
Could you not just say SmartArrayPointer<int> offs
| |
147 | |
148 for (int i = 0; i < n; i++) { | |
149 offsets[i] = -1; | |
150 } | |
151 | |
152 int pos = 0; | |
153 WasmOpcode current = static_cast<WasmOpcode>(va_arg(vl, int)); | |
154 for (size_t i = 0; i < code_size; i++) { | |
155 if (code[i] == current) { | |
156 offsets[pos++] = static_cast<int>(i); | |
157 if (pos == n) break; | |
158 current = static_cast<WasmOpcode>(va_arg(vl, int)); | |
159 } | |
160 } | |
161 va_end(vl); | |
162 | |
163 return offsets; | |
164 } | |
165 | |
166 TEST(Breakpoint_I32Add) { | |
167 static const int kLocalsDeclSize = 1; | |
168 static const int kNumBreakpoints = 3; | |
169 byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; | |
170 SmartArrayPointer<int> offsets = | |
171 Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal, | |
172 kExprI32Add); | |
173 | |
174 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), | |
175 MachineType::Uint32()); | |
176 | |
177 r.Build(code, code + arraysize(code)); | |
142 | 178 |
143 WasmInterpreter* interpreter = r.interpreter(); | 179 WasmInterpreter* interpreter = r.interpreter(); |
144 interpreter->SetBreakpoint(r.function(), 0, true); | 180 WasmInterpreter::Thread& thread = interpreter->GetThread(0); |
181 for (int i = 0; i < kNumBreakpoints; i++) { | |
182 interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[i], | |
183 true); | |
184 } | |
145 | 185 |
146 r.Call(1, 1); | 186 FOR_UINT32_INPUTS(a) { |
147 interpreter->Run(); | 187 for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) { |
148 CHECK_EQ(2, interpreter->GetThread(0).GetReturnValue().to<int32_t>()); | 188 thread.Reset(); |
189 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; | |
190 thread.PushFrame(r.function(), args); | |
191 | |
192 for (int i = 0; i < kNumBreakpoints; i++) { | |
193 thread.Run(); // run to next breakpoint | |
194 // Check the thread stopped at the right pc. | |
195 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); | |
196 CHECK_EQ(kLocalsDeclSize + offsets[i], thread.GetBreakpointPc()); | |
197 } | |
198 | |
199 thread.Run(); // run to completion | |
200 | |
201 // Check the thread finished with the right value. | |
202 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); | |
203 uint32_t expected = (*a) + (b); | |
204 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); | |
205 } | |
206 } | |
207 } | |
208 | |
209 TEST(Step_I32Mul) { | |
210 static const int kTraceLength = 4; | |
211 byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; | |
212 | |
213 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), | |
214 MachineType::Uint32()); | |
215 | |
216 r.Build(code, code + arraysize(code)); | |
217 | |
218 WasmInterpreter* interpreter = r.interpreter(); | |
219 WasmInterpreter::Thread& thread = interpreter->GetThread(0); | |
220 | |
221 FOR_UINT32_INPUTS(a) { | |
222 for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) { | |
223 thread.Reset(); | |
224 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; | |
225 thread.PushFrame(r.function(), args); | |
226 | |
227 // Run instructions one by one. | |
228 for (int i = 0; i < kTraceLength - 1; i++) { | |
229 thread.Step(); | |
230 // Check the thread stopped. | |
231 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); | |
232 } | |
233 | |
234 // Run last instruction. | |
235 thread.Step(); | |
236 | |
237 // Check the thread finished with the right value. | |
238 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); | |
239 uint32_t expected = (*a) * (b); | |
240 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); | |
241 } | |
242 } | |
243 } | |
244 | |
245 TEST(Breakpoint_I32And_disable) { | |
246 static const int kLocalsDeclSize = 1; | |
247 static const int kNumBreakpoints = 1; | |
248 byte code[] = {WASM_I32_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; | |
249 SmartArrayPointer<int> offsets = | |
250 Find(code, sizeof(code), kNumBreakpoints, kExprI32And); | |
251 | |
252 WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), | |
253 MachineType::Uint32()); | |
254 | |
255 r.Build(code, code + arraysize(code)); | |
256 | |
257 WasmInterpreter* interpreter = r.interpreter(); | |
258 WasmInterpreter::Thread& thread = interpreter->GetThread(0); | |
259 | |
260 FOR_UINT32_INPUTS(a) { | |
261 for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) { | |
262 // Run with and without breakpoints. | |
263 for (int do_break = 0; do_break < 2; do_break++) { | |
264 interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0], | |
265 do_break); | |
266 thread.Reset(); | |
267 WasmVal args[] = {WasmVal(*a), WasmVal(b)}; | |
268 thread.PushFrame(r.function(), args); | |
269 | |
270 if (do_break) { | |
271 thread.Run(); // run to next breakpoint | |
272 // Check the thread stopped at the right pc. | |
273 CHECK_EQ(WasmInterpreter::PAUSED, thread.state()); | |
274 CHECK_EQ(kLocalsDeclSize + offsets[0], thread.GetBreakpointPc()); | |
275 } | |
276 | |
277 thread.Run(); // run to completion | |
278 | |
279 // Check the thread finished with the right value. | |
280 CHECK_EQ(WasmInterpreter::FINISHED, thread.state()); | |
281 uint32_t expected = (*a) & (b); | |
282 CHECK_EQ(expected, thread.GetReturnValue().to<uint32_t>()); | |
283 } | |
284 } | |
285 } | |
149 } | 286 } |
150 | 287 |
151 } // namespace wasm | 288 } // namespace wasm |
152 } // namespace internal | 289 } // namespace internal |
153 } // namespace v8 | 290 } // namespace v8 |
OLD | NEW |