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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: test/cctest/wasm/test-wasm-breakpoints.cc
diff --git a/test/cctest/wasm/test-wasm-breakpoints.cc b/test/cctest/wasm/test-wasm-breakpoints.cc
index d2374a44c02c99ff16091d62bd42c1f54ee7b39d..57d36c22dfec0deec1b577e659db22e849fb5295 100644
--- a/test/cctest/wasm/test-wasm-breakpoints.cc
+++ b/test/cctest/wasm/test-wasm-breakpoints.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/debug/debug-interface.h"
+#include "src/property-descriptor.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-objects.h"
@@ -50,6 +51,96 @@ void CheckLocationsFail(WasmCompiledModule *compiled_module,
CHECK(!success);
}
+class CountBreaks {
+ public:
+ explicit CountBreaks(Isolate *isolate) : isolate_(isolate) {
+ current_handler = this;
+ isolate->debug()->SetMessageHandler(&HandleMessage);
+ }
+ ~CountBreaks() {
+ CHECK_EQ(this, current_handler);
+ current_handler = nullptr;
+ isolate_->debug()->SetMessageHandler(nullptr);
+ }
+
+ int count() const { return count_; }
+
+ private:
+ Isolate *isolate_;
+ int count_ = 0;
+
+ 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.
+
+ static void HandleMessage(const v8::Debug::Message &message) {
+ // Ignore responses.
+ if (!message.IsEvent()) return;
+ // Ignore everything except break events.
+ if (message.GetEvent() != v8::DebugEvent::Break) return;
+
+ printf("break!\n");
+ CHECK_NOT_NULL(current_handler);
+ current_handler->count_ += 1;
+ // Don't run into an endless loop.
+ CHECK_GT(100, current_handler->count_);
+
+ const char command[] = "{\"type\":\"request\", \"command\":\"continue\"}";
+ uint16_t command_u16[arraysize(command) - 1];
+ for (unsigned i = 0; i < arraysize(command) - 1; ++i) {
+ command_u16[i] = command[i];
+ }
+ current_handler->isolate_->debug()->EnqueueCommandMessage(
+ ArrayVector(command_u16), message.GetClientData());
+ }
+};
+
+// static
+CountBreaks *CountBreaks::current_handler = nullptr;
+
+Handle<JSObject> MakeFakeBreakpoint(Isolate *isolate, int position) {
+ Handle<JSObject> obj =
+ isolate->factory()->NewJSObject(isolate->object_function());
+ 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
+ PropertyDescriptor desc;
+ desc.set_value(handle(value, isolate));
+ CHECK(JSObject::DefineOwnProperty(
+ isolate, obj,
+ isolate->factory()->InternalizeUtf8String(CStrVector(name)),
+ &desc, Object::DONT_THROW)
+ .FromMaybe(false));
+ };
+ // Generate an "isTriggered" method that always returns true.
+ // This can/must be refactored once we remove remaining JS parts from the
+ // debugger (bug 5530).
+ Handle<String> source = isolate->factory()->NewStringFromStaticChars("true");
+ Handle<Context> context(isolate->context(), isolate);
+ Handle<JSFunction> triggered_fun =
+ Compiler::GetFunctionFromString(context, source, NO_PARSE_RESTRICTION)
+ .ToHandleChecked();
+ SetProperty("isTriggered", *triggered_fun);
+ return obj;
+}
+
+void SetBreakpoint(WasmRunnerBase &runner, int function_index, int byte_offset,
+ int expected_set_byte_offset = -1) {
+ int func_offset =
+ runner.module().module->functions[function_index].code_start_offset;
+ int code_offset = func_offset + byte_offset;
+ if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
+ Handle<WasmInstanceObject> instance = runner.module().instance_object();
+ Handle<WasmCompiledModule> compiled_module(instance->compiled_module());
+ Handle<JSObject> fake_breakpoint_object =
+ MakeFakeBreakpoint(runner.main_isolate(), code_offset);
+ CHECK(WasmCompiledModule::SetBreakPoint(compiled_module, &code_offset,
+ fake_breakpoint_object));
+ int set_byte_offset = code_offset - func_offset;
+ CHECK_EQ(expected_set_byte_offset, set_byte_offset);
+ // Also set breakpoint on the debug info of the instance directly, since the
+ // instance chain is not setup properly in tests.
+ Handle<WasmDebugInfo> debug_info =
+ WasmInstanceObject::GetOrCreateDebugInfo(instance);
+ WasmDebugInfo::SetBreakpoint(debug_info, function_index, set_byte_offset);
+}
+
} // namespace
TEST(CollectPossibleBreakpoints) {
@@ -68,3 +159,95 @@ TEST(CollectPossibleBreakpoints) {
CheckLocations(instance->compiled_module(), {0, 8}, {1, 0}, {});
CheckLocationsFail(instance->compiled_module(), {0, 9}, {1, 0});
}
+
+TEST(TestSimpleBreak) {
+ WasmRunner<int> runner(kExecuteCompiled);
+ WasmFunctionCompiler &f2 = runner.NewFunction<int>();
+
+ BUILD(f2, WASM_NOP, WASM_I32_ADD(WASM_I32V_1(11), WASM_I32V_1(3)));
+ BUILD(runner, WASM_CALL_FUNCTION0(f2.function_index()));
+
+ SetBreakpoint(runner, f2.function_index(), 4, 4);
+ Handle<JSFunction> main_fun_wrapper = runner.module().WrapCode(0);
+ Isolate *isolate = runner.main_isolate();
+
+ CountBreaks count_breaks(isolate);
+ CHECK_EQ(0, count_breaks.count());
+
+ Handle<Object> global(isolate->context()->global_object(), isolate);
+ MaybeHandle<Object> retval =
+ Execution::Call(isolate, main_fun_wrapper, global, 0, nullptr);
+ CHECK(!retval.is_null());
+ int result;
+ CHECK(retval.ToHandleChecked()->ToInt32(&result));
+ CHECK_EQ(14, result);
+
+ CHECK_EQ(1, count_breaks.count());
+}
+
+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
+ // The second and third argument will be combined to an i64.
+ WasmRunner<double, int, int, int, float, double> runner(kExecuteCompiled);
+ WasmFunctionCompiler &f2 =
+ runner.NewFunction<double, int, int64_t, float, double>();
+
+ // Convert all arguments to double, add them and return the sum.
+ BUILD(f2,
+ WASM_F64_ADD( // <0+1+2> + <3>
+ WASM_F64_ADD( // <0+1> + <2>
+ WASM_F64_ADD( // <0> + <1>
+ WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)), // <0> to double
+ WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(1))), // <1> to double
+ WASM_F64_CONVERT_F32(WASM_GET_LOCAL(2))), // <2> to double
+ WASM_GET_LOCAL(3))); // <3>
+
+ BUILD(runner, WASM_GET_LOCAL(0), // first arg
+ WASM_I64_IOR(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(1)), // second arg
+ WASM_I64_SHL(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(2)),
+ WASM_I64V_1(32))),
+ WASM_GET_LOCAL(3), // third arg
+ WASM_GET_LOCAL(4), // fourth arg
+ WASM_CALL_FUNCTION0(f2.function_index()));
+
+ // Set a breakpoint to check that we really execute in the interpreter.
+ SetBreakpoint(runner, f2.function_index(), 1, 1);
+
+ Handle<JSFunction> main_fun_wrapper = runner.module().WrapCode(0);
+ Isolate *isolate = runner.main_isolate();
+ Handle<Object> global(isolate->context()->global_object(), isolate);
+
+ CountBreaks count_breaks(isolate);
+ int num_breaks = 0;
+
+ auto CheckCall = [&](int32_t a, int64_t b, float c, double d) {
+ Handle<Object> args[5] = {
+ isolate->factory()->NewNumberFromInt(a),
+ isolate->factory()->NewNumberFromInt((b & 0xffffffff)),
+ isolate->factory()->NewNumberFromInt((b >> 32) & 0xffffffff),
+ isolate->factory()->NewHeapNumber(c),
+ isolate->factory()->NewHeapNumber(d)};
+
+ CHECK_EQ(num_breaks, count_breaks.count());
+ MaybeHandle<Object> retval = Execution::Call(isolate, main_fun_wrapper,
+ global, arraysize(args), args);
+ CHECK_EQ(++num_breaks, count_breaks.count());
+ double result = retval.ToHandleChecked()->Number();
+ double sum = static_cast<double>(a) + static_cast<double>(b) +
+ static_cast<double>(c) + static_cast<double>(d);
+ CHECK_EQ(sum, result);
+ };
+
+ CheckCall(1, 2, 3, 4);
+ CheckCall(1, 2, 4, 8);
+ CheckCall(std::numeric_limits<int32_t>::max(),
+ std::numeric_limits<int64_t>::max(), 0, 0);
+ CheckCall(0, 0, 0.1f, 0.3);
+ CheckCall(0x0ff00000, 0, 0, 0);
+ CheckCall(0x00000ff0, 0, 0, 0);
+ CheckCall(0, 0x0000000000000ff0, 0, 0);
+ CheckCall(0, 0x000000000ff00000, 0, 0);
+ CheckCall(0, 0x00000ff000000000, 0, 0);
+ CheckCall(0, 0x0ff0000000000000, 0, 0);
+ CheckCall(-3, -11, 0, 0);
+ CheckCall(0, 0, -3, -11);
+}

Powered by Google App Engine
This is Rietveld 408576698