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

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

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

Powered by Google App Engine
This is Rietveld 408576698