Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: test/cctest/wasm/test-wasm-breakpoints.cc

Issue 2629883002: [wasm] Add tests for breakpoints (Closed)
Patch Set: Fix bug in wasm-debug.cc Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "src/debug/debug-interface.h" 5 #include "src/debug/debug-interface.h"
6 #include "src/property-descriptor.h"
6 #include "src/wasm/wasm-macro-gen.h" 7 #include "src/wasm/wasm-macro-gen.h"
7 #include "src/wasm/wasm-objects.h" 8 #include "src/wasm/wasm-objects.h"
8 9
9 #include "test/cctest/cctest.h" 10 #include "test/cctest/cctest.h"
10 #include "test/cctest/compiler/value-helper.h" 11 #include "test/cctest/compiler/value-helper.h"
11 #include "test/cctest/wasm/wasm-run-utils.h" 12 #include "test/cctest/wasm/wasm-run-utils.h"
12 #include "test/common/wasm/test-signatures.h" 13 #include "test/common/wasm/test-signatures.h"
13 14
14 using namespace v8::internal; 15 using namespace v8::internal;
15 using namespace v8::internal::wasm; 16 using namespace v8::internal::wasm;
(...skipping 27 matching lines...) Expand all
43 } 44 }
44 } 45 }
45 void CheckLocationsFail(WasmCompiledModule *compiled_module, 46 void CheckLocationsFail(WasmCompiledModule *compiled_module,
46 debug::Location start, debug::Location end) { 47 debug::Location start, debug::Location end) {
47 std::vector<debug::Location> locations; 48 std::vector<debug::Location> locations;
48 bool success = 49 bool success =
49 compiled_module->GetPossibleBreakpoints(start, end, &locations); 50 compiled_module->GetPossibleBreakpoints(start, end, &locations);
50 CHECK(!success); 51 CHECK(!success);
51 } 52 }
52 53
54 class CountBreaks {
55 public:
56 explicit CountBreaks(Isolate *isolate) : isolate_(isolate) {
57 current_handler = this;
58 isolate->debug()->SetMessageHandler(&HandleMessage);
59 }
60 ~CountBreaks() {
61 CHECK_EQ(this, current_handler);
62 current_handler = nullptr;
63 isolate_->debug()->SetMessageHandler(nullptr);
64 }
65
66 int count() const { return count_; }
67
68 private:
69 Isolate *isolate_;
70 int count_ = 0;
71
72 static CountBreaks *current_handler;
titzer 2017/01/16 13:55:27 Type* instead of Type *, here and elsewhere.
Clemens Hammacher 2017/01/16 18:51:31 Same.
73
74 static void HandleMessage(const v8::Debug::Message &message) {
75 // Ignore responses.
76 if (!message.IsEvent()) return;
77 // Ignore everything except break events.
78 if (message.GetEvent() != v8::DebugEvent::Break) return;
79
80 printf("break!\n");
81 CHECK_NOT_NULL(current_handler);
82 current_handler->count_ += 1;
83 // Don't run into an endless loop.
84 CHECK_GT(100, current_handler->count_);
85
86 const char command[] = "{\"type\":\"request\", \"command\":\"continue\"}";
87 uint16_t command_u16[arraysize(command) - 1];
88 for (unsigned i = 0; i < arraysize(command) - 1; ++i) {
89 command_u16[i] = command[i];
90 }
91 current_handler->isolate_->debug()->EnqueueCommandMessage(
92 ArrayVector(command_u16), message.GetClientData());
93 }
94 };
95
96 // static
97 CountBreaks *CountBreaks::current_handler = nullptr;
98
99 Handle<JSObject> MakeFakeBreakpoint(Isolate *isolate, int position) {
100 Handle<JSObject> obj =
101 isolate->factory()->NewJSObject(isolate->object_function());
102 auto SetProperty = [obj, isolate](const char *name, Object *value) {
titzer 2017/01/16 13:55:27 Not sure why you need a lambda here, since this is
Clemens Hammacher 2017/01/16 18:51:31 Oh, right. It was more properties before. Removed
103 PropertyDescriptor desc;
104 desc.set_value(handle(value, isolate));
105 CHECK(JSObject::DefineOwnProperty(
106 isolate, obj,
107 isolate->factory()->InternalizeUtf8String(CStrVector(name)),
108 &desc, Object::DONT_THROW)
109 .FromMaybe(false));
110 };
111 // Generate an "isTriggered" method that always returns true.
112 // This can/must be refactored once we remove remaining JS parts from the
113 // debugger (bug 5530).
114 Handle<String> source = isolate->factory()->NewStringFromStaticChars("true");
115 Handle<Context> context(isolate->context(), isolate);
116 Handle<JSFunction> triggered_fun =
117 Compiler::GetFunctionFromString(context, source, NO_PARSE_RESTRICTION)
118 .ToHandleChecked();
119 SetProperty("isTriggered", *triggered_fun);
120 return obj;
121 }
122
123 void SetBreakpoint(WasmRunnerBase &runner, int function_index, int byte_offset,
124 int expected_set_byte_offset = -1) {
125 int func_offset =
126 runner.module().module->functions[function_index].code_start_offset;
127 int code_offset = func_offset + byte_offset;
128 if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
129 Handle<WasmInstanceObject> instance = runner.module().instance_object();
130 Handle<WasmCompiledModule> compiled_module(instance->compiled_module());
131 Handle<JSObject> fake_breakpoint_object =
132 MakeFakeBreakpoint(runner.main_isolate(), code_offset);
133 CHECK(WasmCompiledModule::SetBreakPoint(compiled_module, &code_offset,
134 fake_breakpoint_object));
135 int set_byte_offset = code_offset - func_offset;
136 CHECK_EQ(expected_set_byte_offset, set_byte_offset);
137 // Also set breakpoint on the debug info of the instance directly, since the
138 // instance chain is not setup properly in tests.
139 Handle<WasmDebugInfo> debug_info =
140 WasmInstanceObject::GetOrCreateDebugInfo(instance);
141 WasmDebugInfo::SetBreakpoint(debug_info, function_index, set_byte_offset);
142 }
143
53 } // namespace 144 } // namespace
54 145
55 TEST(CollectPossibleBreakpoints) { 146 TEST(CollectPossibleBreakpoints) {
56 WasmRunner<int> runner(kExecuteCompiled); 147 WasmRunner<int> runner(kExecuteCompiled);
57 148
58 BUILD(runner, WASM_NOP, WASM_I32_ADD(WASM_ZERO, WASM_ONE)); 149 BUILD(runner, WASM_NOP, WASM_I32_ADD(WASM_ZERO, WASM_ONE));
59 150
60 Handle<WasmInstanceObject> instance = runner.module().instance_object(); 151 Handle<WasmInstanceObject> instance = runner.module().instance_object();
61 std::vector<debug::Location> locations; 152 std::vector<debug::Location> locations;
62 CheckLocations(instance->compiled_module(), {0, 0}, {1, 0}, 153 CheckLocations(instance->compiled_module(), {0, 0}, {1, 0},
63 {{0, 1}, {0, 2}, {0, 4}, {0, 6}, {0, 7}}); 154 {{0, 1}, {0, 2}, {0, 4}, {0, 6}, {0, 7}});
64 CheckLocations(instance->compiled_module(), {0, 2}, {0, 4}, {{0, 2}}); 155 CheckLocations(instance->compiled_module(), {0, 2}, {0, 4}, {{0, 2}});
65 CheckLocations(instance->compiled_module(), {0, 2}, {0, 5}, {{0, 2}, {0, 4}}); 156 CheckLocations(instance->compiled_module(), {0, 2}, {0, 5}, {{0, 2}, {0, 4}});
66 CheckLocations(instance->compiled_module(), {0, 7}, {0, 8}, {{0, 7}}); 157 CheckLocations(instance->compiled_module(), {0, 7}, {0, 8}, {{0, 7}});
67 CheckLocations(instance->compiled_module(), {0, 7}, {1, 0}, {{0, 7}}); 158 CheckLocations(instance->compiled_module(), {0, 7}, {1, 0}, {{0, 7}});
68 CheckLocations(instance->compiled_module(), {0, 8}, {1, 0}, {}); 159 CheckLocations(instance->compiled_module(), {0, 8}, {1, 0}, {});
69 CheckLocationsFail(instance->compiled_module(), {0, 9}, {1, 0}); 160 CheckLocationsFail(instance->compiled_module(), {0, 9}, {1, 0});
70 } 161 }
162
163 TEST(TestSimpleBreak) {
164 WasmRunner<int> runner(kExecuteCompiled);
165 WasmFunctionCompiler &f2 = runner.NewFunction<int>();
166
167 BUILD(f2, WASM_NOP, WASM_I32_ADD(WASM_I32V_1(11), WASM_I32V_1(3)));
168 BUILD(runner, WASM_CALL_FUNCTION0(f2.function_index()));
169
170 SetBreakpoint(runner, f2.function_index(), 4, 4);
171 Handle<JSFunction> main_fun_wrapper = runner.module().WrapCode(0);
172 Isolate *isolate = runner.main_isolate();
173
174 CountBreaks count_breaks(isolate);
175 CHECK_EQ(0, count_breaks.count());
176
177 Handle<Object> global(isolate->context()->global_object(), isolate);
178 MaybeHandle<Object> retval =
179 Execution::Call(isolate, main_fun_wrapper, global, 0, nullptr);
180 CHECK(!retval.is_null());
181 int result;
182 CHECK(retval.ToHandleChecked()->ToInt32(&result));
183 CHECK_EQ(14, result);
184
185 CHECK_EQ(1, count_breaks.count());
186 }
187
188 TEST(TestArgumentPassing) {
titzer 2017/01/16 13:55:27 This test is a bit too complicated, IMO. It is te
Clemens Hammacher 2017/01/16 18:51:31 Counting the number of breaks is basically only th
189 // The second and third argument will be combined to an i64.
190 WasmRunner<double, int, int, int, float, double> runner(kExecuteCompiled);
191 WasmFunctionCompiler &f2 =
192 runner.NewFunction<double, int, int64_t, float, double>();
193
194 // Convert all arguments to double, add them and return the sum.
195 BUILD(f2,
196 WASM_F64_ADD( // <0+1+2> + <3>
197 WASM_F64_ADD( // <0+1> + <2>
198 WASM_F64_ADD( // <0> + <1>
199 WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)), // <0> to double
200 WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(1))), // <1> to double
201 WASM_F64_CONVERT_F32(WASM_GET_LOCAL(2))), // <2> to double
202 WASM_GET_LOCAL(3))); // <3>
203
204 BUILD(runner, WASM_GET_LOCAL(0), // first arg
205 WASM_I64_IOR(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(1)), // second arg
206 WASM_I64_SHL(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(2)),
207 WASM_I64V_1(32))),
208 WASM_GET_LOCAL(3), // third arg
209 WASM_GET_LOCAL(4), // fourth arg
210 WASM_CALL_FUNCTION0(f2.function_index()));
211
212 // Set a breakpoint to check that we really execute in the interpreter.
213 SetBreakpoint(runner, f2.function_index(), 1, 1);
214
215 Handle<JSFunction> main_fun_wrapper = runner.module().WrapCode(0);
216 Isolate *isolate = runner.main_isolate();
217 Handle<Object> global(isolate->context()->global_object(), isolate);
218
219 CountBreaks count_breaks(isolate);
220 int num_breaks = 0;
221
222 auto CheckCall = [&](int32_t a, int64_t b, float c, double d) {
223 Handle<Object> args[5] = {
224 isolate->factory()->NewNumberFromInt(a),
225 isolate->factory()->NewNumberFromInt((b & 0xffffffff)),
226 isolate->factory()->NewNumberFromInt((b >> 32) & 0xffffffff),
227 isolate->factory()->NewHeapNumber(c),
228 isolate->factory()->NewHeapNumber(d)};
229
230 CHECK_EQ(num_breaks, count_breaks.count());
231 MaybeHandle<Object> retval = Execution::Call(isolate, main_fun_wrapper,
232 global, arraysize(args), args);
233 CHECK_EQ(++num_breaks, count_breaks.count());
234 double result = retval.ToHandleChecked()->Number();
235 double sum = static_cast<double>(a) + static_cast<double>(b) +
236 static_cast<double>(c) + static_cast<double>(d);
237 CHECK_EQ(sum, result);
238 };
239
240 CheckCall(1, 2, 3, 4);
241 CheckCall(1, 2, 4, 8);
242 CheckCall(std::numeric_limits<int32_t>::max(),
243 std::numeric_limits<int64_t>::max(), 0, 0);
244 CheckCall(0, 0, 0.1f, 0.3);
245 CheckCall(0x0ff00000, 0, 0, 0);
246 CheckCall(0x00000ff0, 0, 0, 0);
247 CheckCall(0, 0x0000000000000ff0, 0, 0);
248 CheckCall(0, 0x000000000ff00000, 0, 0);
249 CheckCall(0, 0x00000ff000000000, 0, 0);
250 CheckCall(0, 0x0ff0000000000000, 0, 0);
251 CheckCall(-3, -11, 0, 0);
252 CheckCall(0, 0, -3, -11);
253 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698