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

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

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

Powered by Google App Engine
This is Rietveld 408576698