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

Side by Side Diff: test/cctest/wasm/test-wasm-trap-position.cc

Issue 1924253002: [wasm] Patch trapping position into stack trace (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@pass-wasm-position-to-runtime
Patch Set: add TODO with tracking bug Created 4 years, 7 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
« no previous file with comments | « test/cctest/wasm/test-wasm-stack.cc ('k') | test/mjsunit/wasm/stack.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/wasm/wasm-macro-gen.h" 5 #include "src/wasm/wasm-macro-gen.h"
6 6
7 #include "test/cctest/cctest.h" 7 #include "test/cctest/cctest.h"
8 #include "test/cctest/compiler/value-helper.h" 8 #include "test/cctest/compiler/value-helper.h"
9 #include "test/cctest/wasm/test-signatures.h" 9 #include "test/cctest/wasm/test-signatures.h"
10 #include "test/cctest/wasm/wasm-run-utils.h" 10 #include "test/cctest/wasm/wasm-run-utils.h"
(...skipping 13 matching lines...) Expand all
24 const char* exp_ = (exp); \ 24 const char* exp_ = (exp); \
25 const char* found_ = (found); \ 25 const char* found_ = (found); \
26 DCHECK_NOT_NULL(exp); \ 26 DCHECK_NOT_NULL(exp); \
27 if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \ 27 if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \
28 V8_Fatal(__FILE__, __LINE__, \ 28 V8_Fatal(__FILE__, __LINE__, \
29 "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \ 29 "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
30 exp_, found_ ? found_ : "<null>"); \ 30 exp_, found_ ? found_ : "<null>"); \
31 } \ 31 } \
32 } while (0) 32 } while (0)
33 33
34 void PrintStackTrace(v8::Local<v8::StackTrace> stack) {
35 printf("Stack Trace (length %d):\n", stack->GetFrameCount());
36 for (int i = 0, e = stack->GetFrameCount(); i != e; ++i) {
37 v8::Local<v8::StackFrame> frame = stack->GetFrame(i);
38 v8::Local<v8::String> script = frame->GetScriptName();
39 v8::Local<v8::String> func = frame->GetFunctionName();
40 printf("[%d] (%s) %s:%d:%d\n", i,
41 script.IsEmpty() ? "<null>" : *v8::String::Utf8Value(script),
42 func.IsEmpty() ? "<null>" : *v8::String::Utf8Value(func),
43 frame->GetLineNumber(), frame->GetColumn());
44 }
45 }
46
47 struct ExceptionInfo { 34 struct ExceptionInfo {
48 const char* func_name; 35 const char* func_name;
49 int line_nr; 36 int line_nr;
50 int column; 37 int column;
51 }; 38 };
52 39
53 template <int N> 40 template <int N>
54 void CheckExceptionInfos(Isolate* isolate, Handle<Object> exc, 41 void CheckExceptionInfos(Isolate* isolate, Handle<Object> exc,
55 const ExceptionInfo (&excInfos)[N]) { 42 const ExceptionInfo (&excInfos)[N]) {
56 // Check that it's indeed an Error object. 43 // Check that it's indeed an Error object.
57 CHECK(Object::IsErrorObject(isolate, exc)); 44 CHECK(Object::IsErrorObject(isolate, exc));
58 45
59 // Extract stack frame from the exception. 46 // Extract stack frame from the exception.
60 Local<v8::Value> localExc = Utils::ToLocal(exc); 47 Local<v8::Value> localExc = Utils::ToLocal(exc);
61 v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc); 48 v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
62 PrintStackTrace(stack);
63 CHECK(!stack.IsEmpty()); 49 CHECK(!stack.IsEmpty());
64 CHECK_EQ(N, stack->GetFrameCount()); 50 CHECK_EQ(N, stack->GetFrameCount());
65 51
66 for (int frameNr = 0; frameNr < N; ++frameNr) { 52 for (int frameNr = 0; frameNr < N; ++frameNr) {
67 v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr); 53 v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr);
68 v8::String::Utf8Value funName(frame->GetFunctionName()); 54 v8::String::Utf8Value funName(frame->GetFunctionName());
69 CHECK_CSTREQ(excInfos[frameNr].func_name, *funName); 55 CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
70 CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber()); 56 CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
71 CHECK_EQ(excInfos[frameNr].column, frame->GetColumn()); 57 CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
72 } 58 }
73 } 59 }
74 60
75 } // namespace 61 } // namespace
76 62
77 // Call from JS to WASM to JS and throw an Error from JS. 63 // Trigger a trap for executing unreachable.
78 TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) { 64 TEST(Unreachable) {
79 TestSignatures sigs; 65 TestSignatures sigs;
80 TestingModule module; 66 TestingModule module;
81 67
82 // Initialize WasmFunctionCompiler first, since it sets up the HandleScope. 68 WasmFunctionCompiler comp1(sigs.v_v(), &module,
83 WasmFunctionCompiler comp1(sigs.v_v(), &module); 69 ArrayVector("exec_unreachable"));
84 70 // Set the execution context, such that a runtime error can be thrown.
85 uint32_t js_throwing_index = module.AddJsFunction( 71 comp1.SetModuleContext();
86 sigs.v_v(), 72 BUILD(comp1, WASM_UNREACHABLE);
87 "(function js() {\n function a() {\n throw new Error(); };\n a(); })");
88
89 // Add a nop such that we don't always get position 1.
90 BUILD(comp1, WASM_NOP, WASM_CALL_FUNCTION0(js_throwing_index));
91 uint32_t wasm_index = comp1.CompileAndAdd(); 73 uint32_t wasm_index = comp1.CompileAndAdd();
92 74
93 WasmFunctionCompiler comp2(sigs.v_v(), &module); 75 Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index);
94 BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index));
95 uint32_t wasm_index_2 = comp2.CompileAndAdd();
96
97 Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
98 76
99 Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( 77 Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
100 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( 78 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
101 CompileRun("(function callFn(fn) { fn(); })")))); 79 CompileRun("(function callFn(fn) { fn(); })"))));
102 80
103 Isolate* isolate = js_wasm_wrapper->GetIsolate(); 81 Isolate* isolate = js_wasm_wrapper->GetIsolate();
104 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10, 82 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
105 v8::StackTrace::kOverview); 83 v8::StackTrace::kOverview);
106 Handle<Object> global(isolate->context()->global_object(), isolate); 84 Handle<Object> global(isolate->context()->global_object(), isolate);
107 MaybeHandle<Object> maybe_exc; 85 MaybeHandle<Object> maybe_exc;
108 Handle<Object> args[] = {js_wasm_wrapper}; 86 Handle<Object> args[] = {js_wasm_wrapper};
109 MaybeHandle<Object> returnObjMaybe = 87 MaybeHandle<Object> returnObjMaybe =
110 Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); 88 Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
111 CHECK(returnObjMaybe.is_null()); 89 CHECK(returnObjMaybe.is_null());
112 90
113 // Line number is 1-based, with 0 == kNoLineNumberInfo.
114 ExceptionInfo expected_exceptions[] = { 91 ExceptionInfo expected_exceptions[] = {
115 {"a", 3, 8}, // - 92 {"<WASM>", static_cast<int>(wasm_index), 1}, // --
116 {"js", 4, 2}, // - 93 {"callFn", 1, 24} // --
117 {"<WASM>", static_cast<int>(wasm_index), 2}, // -
118 {"<WASM>", static_cast<int>(wasm_index_2), 1}, // -
119 {"callFn", 1, 24} // -
120 }; 94 };
121 CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(), 95 CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
122 expected_exceptions); 96 expected_exceptions);
123 } 97 }
124 98
125 // Trigger a trap in WASM, stack should be JS -> WASM -> WASM. 99 // Trigger a trap for loading from out-of-bounds.
126 TEST(CollectDetailedWasmStack_WasmError) { 100 TEST(IllegalLoad) {
127 TestSignatures sigs; 101 TestSignatures sigs;
128 TestingModule module; 102 TestingModule module;
129 103
130 WasmFunctionCompiler comp1(sigs.i_v(), &module, 104 WasmFunctionCompiler comp1(sigs.v_v(), &module, ArrayVector("mem_oob"));
131 ArrayVector("exec_unreachable"));
132 // Set the execution context, such that a runtime error can be thrown. 105 // Set the execution context, such that a runtime error can be thrown.
133 comp1.SetModuleContext(); 106 comp1.SetModuleContext();
134 BUILD(comp1, WASM_UNREACHABLE); 107 BUILD(comp1, WASM_IF(WASM_ONE,
108 WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-3))));
135 uint32_t wasm_index = comp1.CompileAndAdd(); 109 uint32_t wasm_index = comp1.CompileAndAdd();
136 110
137 WasmFunctionCompiler comp2(sigs.i_v(), &module, 111 WasmFunctionCompiler comp2(sigs.v_v(), &module, ArrayVector("call_mem_oob"));
138 ArrayVector("call_exec_unreachable")); 112 // Insert a NOP such that the position of the call is not one.
139 BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index)); 113 BUILD(comp2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index));
140 uint32_t wasm_index_2 = comp2.CompileAndAdd(); 114 uint32_t wasm_index_2 = comp2.CompileAndAdd();
141 115
142 Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2); 116 Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
143 117
144 Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( 118 Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
145 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( 119 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
146 CompileRun("(function callFn(fn) { fn(); })")))); 120 CompileRun("(function callFn(fn) { fn(); })"))));
147 121
148 Isolate* isolate = js_wasm_wrapper->GetIsolate(); 122 Isolate* isolate = js_wasm_wrapper->GetIsolate();
149 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10, 123 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
150 v8::StackTrace::kOverview); 124 v8::StackTrace::kOverview);
151 Handle<Object> global(isolate->context()->global_object(), isolate); 125 Handle<Object> global(isolate->context()->global_object(), isolate);
152 MaybeHandle<Object> maybe_exc; 126 MaybeHandle<Object> maybe_exc;
153 Handle<Object> args[] = {js_wasm_wrapper}; 127 Handle<Object> args[] = {js_wasm_wrapper};
154 MaybeHandle<Object> maybe_return_obj = 128 MaybeHandle<Object> returnObjMaybe =
155 Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); 129 Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
156 CHECK(maybe_return_obj.is_null()); 130 CHECK(returnObjMaybe.is_null());
157 131
158 // Line number is 1-based, with 0 == kNoLineNumberInfo. 132 // Line number is 1-based, with 0 == kNoLineNumberInfo.
159 ExceptionInfo expected_exceptions[] = { 133 ExceptionInfo expected_exceptions[] = {
160 // TODO(clemens): position should be 1 134 {"<WASM>", static_cast<int>(wasm_index), 6}, // --
161 {"<WASM>", static_cast<int>(wasm_index), -1}, // - 135 {"<WASM>", static_cast<int>(wasm_index_2), 2}, // --
162 {"<WASM>", static_cast<int>(wasm_index_2), 1}, // - 136 {"callFn", 1, 24} // --
163 {"callFn", 1, 24} //-
164 }; 137 };
165 CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(), 138 CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
166 expected_exceptions); 139 expected_exceptions);
167 } 140 }
OLDNEW
« no previous file with comments | « test/cctest/wasm/test-wasm-stack.cc ('k') | test/mjsunit/wasm/stack.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698