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

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

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

Powered by Google App Engine
This is Rietveld 408576698