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

Side by Side Diff: src/inspector/wasm-translation.cc

Issue 2493773003: [inspector] Introduce translation of wasm frames (Closed)
Patch Set: Very last-minute changes Created 4 years, 1 month 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 | « src/inspector/wasm-translation.h ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/inspector/wasm-translation.h"
6
7 #include <algorithm>
8
9 #include "src/debug/debug-interface.h"
10 #include "src/inspector/protocol/Debugger.h"
11 #include "src/inspector/script-breakpoint.h"
12 #include "src/inspector/string-util.h"
13 #include "src/inspector/v8-debugger-agent-impl.h"
14 #include "src/inspector/v8-debugger-script.h"
15 #include "src/inspector/v8-debugger.h"
16 #include "src/inspector/v8-inspector-impl.h"
17
18 using namespace v8_inspector;
19 using namespace v8;
20
21 namespace {
22 int GetScriptId(Isolate *isolate, Local<Object> script_wrapper) {
23 Local<Value> script_id = script_wrapper
24 ->Get(isolate->GetCurrentContext(),
25 toV8StringInternalized(isolate, "id"))
26 .ToLocalChecked();
27 DCHECK(script_id->IsInt32());
28 return script_id->Int32Value(isolate->GetCurrentContext()).FromJust();
29 }
30
31 String16 GetScriptName(Isolate *isolate, Local<Object> script_wrapper) {
32 Local<Value> script_name = script_wrapper
33 ->Get(isolate->GetCurrentContext(),
34 toV8StringInternalized(isolate, "name"))
35 .ToLocalChecked();
36 DCHECK(script_name->IsString());
37 return toProtocolString(script_name.As<String>());
38 }
39
40 } // namespace
41
42 class WasmTranslation::TranslatorImpl {
43 public:
44 struct TransLocation {
45 WasmTranslation *translation;
46 String16 script_id;
47 int line;
48 int column;
49 int context_group_id;
50 TransLocation(WasmTranslation *translation, String16 script_id, int line,
51 int column, int context_group_id)
52 : translation(translation),
53 script_id(script_id),
54 line(line),
55 column(column),
56 context_group_id(context_group_id) {}
57 };
58
59 virtual void Translate(TransLocation *loc) = 0;
60 virtual void TranslateBack(TransLocation *loc) = 0;
61
62 class RawTranslator;
63 class DisassemblingTranslator;
64 };
65
66 class WasmTranslation::TranslatorImpl::RawTranslator
67 : public WasmTranslation::TranslatorImpl {
68 public:
69 void Translate(TransLocation *loc) {}
70 void TranslateBack(TransLocation *loc) {}
71 };
72
73 class WasmTranslation::TranslatorImpl::DisassemblingTranslator
74 : public WasmTranslation::TranslatorImpl {
75 using OffsetTable = std::vector<std::tuple<uint32_t, int, int>>;
76
77 public:
78 DisassemblingTranslator(Isolate *isolate, Local<Object> script)
79 : script_(isolate, script) {}
80
81 void Translate(TransLocation *loc) {
82 const OffsetTable &offset_table = GetOffsetTable(loc);
83 DCHECK(!offset_table.empty());
84 uint32_t byte_offset = static_cast<uint32_t>(loc->column);
85
86 // Binary search for the given offset.
87 unsigned left = 0; // inclusive
88 unsigned right = static_cast<unsigned>(offset_table.size()); // exclusive
89 while (right - left > 1) {
90 unsigned mid = (left + right) / 2;
91 if (std::get<0>(offset_table[mid]) <= byte_offset) {
92 left = mid;
93 } else {
94 right = mid;
95 }
96 }
97
98 loc->script_id = GetFakeScriptId(loc);
99 if (std::get<0>(offset_table[left]) == byte_offset) {
100 loc->line = std::get<1>(offset_table[left]);
101 loc->column = std::get<2>(offset_table[left]);
102 } else {
103 loc->line = 0;
104 loc->column = 0;
105 }
106 }
107
108 void TranslateBack(TransLocation *loc) {
109 int func_index = GetFunctionIndexFromFakeScriptId(loc->script_id);
110 const OffsetTable *reverse_table = GetReverseTable(func_index);
111 if (!reverse_table) return;
112 DCHECK(!reverse_table->empty());
113
114 // Binary search for the given line and column.
115 unsigned left = 0; // inclusive
116 unsigned right = static_cast<unsigned>(reverse_table->size()); // exclusive
117 while (right - left > 1) {
118 unsigned mid = (left + right) / 2;
119 auto &entry = (*reverse_table)[mid];
120 if (std::get<1>(entry) < loc->line ||
121 (std::get<1>(entry) == loc->line &&
122 std::get<2>(entry) <= loc->column)) {
123 left = mid;
124 } else {
125 right = mid;
126 }
127 }
128
129 int found_byte_offset = 0;
130 // If we found an exact match, use it. Otherwise check whether the next
131 // bigger entry is still in the same line. Report that one then.
132 if (std::get<1>((*reverse_table)[left]) == loc->line &&
133 std::get<2>((*reverse_table)[left]) == loc->column) {
134 found_byte_offset = std::get<0>((*reverse_table)[left]);
135 } else if (left + 1 < reverse_table->size() &&
136 std::get<1>((*reverse_table)[left + 1]) == loc->line) {
137 found_byte_offset = std::get<0>((*reverse_table)[left + 1]);
138 }
139
140 v8::Isolate *isolate = loc->translation->isolate_;
141 loc->script_id =
142 String16::fromInteger(GetScriptId(isolate, script_.Get(isolate)));
143 loc->line = func_index;
144 loc->column = found_byte_offset;
145 }
146
147 private:
148 String16 GetFakeScriptUrl(const TransLocation *loc) {
149 v8::Isolate *isolate = loc->translation->isolate_;
150 String16 script_name = GetScriptName(isolate, script_.Get(isolate));
151 return String16::concat("wasm://wasm/", script_name, '/', script_name, '-',
152 String16::fromInteger(loc->line));
153 }
154
155 String16 GetFakeScriptId(const TransLocation *loc) {
156 return String16::concat(loc->script_id, '-',
157 String16::fromInteger(loc->line));
158 }
159
160 int GetFunctionIndexFromFakeScriptId(const String16 &fake_script_id) {
161 size_t last_dash_pos = fake_script_id.reverseFind('-');
162 DCHECK_GT(fake_script_id.length(), last_dash_pos);
163 bool ok = true;
164 int func_index = fake_script_id.substring(last_dash_pos + 1).toInteger(&ok);
165 DCHECK(ok);
166 return func_index;
167 }
168
169 const OffsetTable &GetOffsetTable(const TransLocation *loc) {
170 int func_index = loc->line;
171 auto it = offset_tables_.find(func_index);
172 if (it != offset_tables_.end()) return it->second;
173
174 v8::Isolate *isolate = loc->translation->isolate_;
175 std::pair<std::string, OffsetTable> disassembly =
176 DebugInterface::DisassembleWasmFunction(isolate, script_.Get(isolate),
177 func_index);
178
179 it = offset_tables_
180 .insert(std::make_pair(func_index, std::move(disassembly.second)))
181 .first;
182
183 String16 fake_script_id = GetFakeScriptId(loc);
184 String16 fake_script_url = GetFakeScriptUrl(loc);
185 String16 source(disassembly.first.data(), disassembly.first.length());
186 std::unique_ptr<V8DebuggerScript> fake_script(new V8DebuggerScript(
187 fake_script_id, std::move(fake_script_url), source));
188
189 loc->translation->AddFakeScript(std::move(fake_script), this,
190 loc->context_group_id);
191
192 return it->second;
193 }
194
195 const OffsetTable *GetReverseTable(int func_index) {
196 auto it = reverse_tables_.find(func_index);
197 if (it != reverse_tables_.end()) return &it->second;
198
199 // Find offset table, copy and sort it to get reverse table.
200 it = offset_tables_.find(func_index);
201 if (it == offset_tables_.end()) return nullptr;
202
203 OffsetTable reverse_table = it->second;
204 // Order by line, column, then byte offset.
205 auto cmp = [](std::tuple<uint32_t, int, int> el1,
206 std::tuple<uint32_t, int, int> el2) {
207 if (std::get<1>(el1) != std::get<1>(el2))
208 return std::get<1>(el1) < std::get<1>(el2);
209 if (std::get<2>(el1) != std::get<2>(el2))
210 return std::get<2>(el1) < std::get<2>(el2);
211 return std::get<0>(el1) < std::get<0>(el2);
212 };
213 std::sort(reverse_table.begin(), reverse_table.end(), cmp);
214
215 auto inserted = reverse_tables_.insert(
216 std::make_pair(func_index, std::move(reverse_table)));
217 DCHECK(inserted.second);
218 return &inserted.first->second;
219 }
220
221 Global<Object> script_;
222
223 // We assume to only disassemble a subset of the functions, so store them in a
224 // map instead of an array.
225 std::unordered_map<int, const OffsetTable> offset_tables_;
226 std::unordered_map<int, const OffsetTable> reverse_tables_;
227 };
228
229 WasmTranslation::WasmTranslation(v8::Isolate *isolate, V8Debugger *debugger)
230 : isolate_(isolate), debugger_(debugger), mode_(Disassemble) {}
231
232 WasmTranslation::~WasmTranslation() { Clear(); }
233
234 void WasmTranslation::AddScript(Local<Object> script_wrapper) {
235 int script_id = GetScriptId(isolate_, script_wrapper);
236 DCHECK_EQ(0U, wasm_translators_.count(script_id));
237 std::unique_ptr<TranslatorImpl> impl;
238 switch (mode_) {
239 case Raw:
240 impl.reset(new TranslatorImpl::RawTranslator());
241 break;
242 case Disassemble:
243 impl.reset(new TranslatorImpl::DisassemblingTranslator(isolate_,
244 script_wrapper));
245 break;
246 }
247 DCHECK(impl);
248 wasm_translators_.insert(std::make_pair(script_id, std::move(impl)));
249 }
250
251 void WasmTranslation::Clear() {
252 wasm_translators_.clear();
253 fake_scripts_.clear();
254 }
255
256 // Translation "forward" (to artificial scripts).
257 bool WasmTranslation::TranslateWasmScriptLocationToProtocolLocation(
258 String16 *script_id, int *line_number, int *column_number,
259 int context_group_id) {
260 DCHECK(script_id && line_number && column_number);
261 bool ok = true;
262 int script_id_int = script_id->toInteger(&ok);
263 if (!ok) return false;
264
265 auto it = wasm_translators_.find(script_id_int);
266 if (it == wasm_translators_.end()) return false;
267 TranslatorImpl *translator = it->second.get();
268
269 TranslatorImpl::TransLocation trans_loc(this, std::move(*script_id),
270 *line_number, *column_number,
271 context_group_id);
272 translator->Translate(&trans_loc);
273
274 *script_id = std::move(trans_loc.script_id);
275 *line_number = trans_loc.line;
276 *column_number = trans_loc.column;
277
278 return true;
279 }
280
281 // Translation "backward" (from artificial to real scripts).
282 bool WasmTranslation::TranslateProtocolLocationToWasmScriptLocation(
283 String16 *script_id, int *line_number, int *column_number) {
284 auto it = fake_scripts_.find(*script_id);
285 if (it == fake_scripts_.end()) return false;
286 TranslatorImpl *translator = it->second;
287
288 TranslatorImpl::TransLocation trans_loc(this, std::move(*script_id),
289 *line_number, *column_number, -1);
290 translator->TranslateBack(&trans_loc);
291
292 *script_id = std::move(trans_loc.script_id);
293 *line_number = trans_loc.line;
294 *column_number = trans_loc.column;
295
296 return true;
297 }
298
299 void WasmTranslation::AddFakeScript(
300 std::unique_ptr<V8DebuggerScript> fake_script, TranslatorImpl *translator,
301 int context_group_id) {
302 bool inserted =
303 fake_scripts_.insert(std::make_pair(fake_script->scriptId(), translator))
304 .second;
305 DCHECK(inserted);
306 USE(inserted);
307 V8DebuggerAgentImpl *agent =
308 debugger_->inspector()->enabledDebuggerAgentForGroup(context_group_id);
309 agent->didParseSource(std::move(fake_script), true);
310 }
OLDNEW
« no previous file with comments | « src/inspector/wasm-translation.h ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698