| OLD | NEW | 
|---|
| 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" | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 26     int line; | 26     int line; | 
| 27     int column; | 27     int column; | 
| 28     TransLocation(WasmTranslation *translation, String16 script_id, int line, | 28     TransLocation(WasmTranslation *translation, String16 script_id, int line, | 
| 29                   int column) | 29                   int column) | 
| 30         : translation(translation), | 30         : translation(translation), | 
| 31           script_id(script_id), | 31           script_id(script_id), | 
| 32           line(line), | 32           line(line), | 
| 33           column(column) {} | 33           column(column) {} | 
| 34   }; | 34   }; | 
| 35 | 35 | 
|  | 36   TranslatorImpl(WasmTranslation* translation, int script_id) { | 
|  | 37     DCHECK_EQ(0, translation->wasm_translators_.count(script_id)); | 
|  | 38     translation->wasm_translators_.insert( | 
|  | 39         std::make_pair(script_id, std::unique_ptr<TranslatorImpl>(this))); | 
|  | 40   } | 
|  | 41 | 
| 36   virtual void Translate(TransLocation *loc) = 0; | 42   virtual void Translate(TransLocation *loc) = 0; | 
| 37   virtual void TranslateBack(TransLocation *loc) = 0; | 43   virtual void TranslateBack(TransLocation *loc) = 0; | 
| 38 | 44 | 
| 39   class RawTranslator; | 45   class RawTranslator; | 
| 40   class DisassemblingTranslator; | 46   class DisassemblingTranslator; | 
| 41 }; | 47 }; | 
| 42 | 48 | 
| 43 class WasmTranslation::TranslatorImpl::RawTranslator | 49 class WasmTranslation::TranslatorImpl::RawTranslator | 
| 44     : public WasmTranslation::TranslatorImpl { | 50     : public WasmTranslation::TranslatorImpl { | 
| 45  public: | 51  public: | 
|  | 52   RawTranslator(WasmTranslation* translation, Local<debug::WasmScript> script) | 
|  | 53       : TranslatorImpl(translation, script->Id()) {} | 
| 46   void Translate(TransLocation *loc) {} | 54   void Translate(TransLocation *loc) {} | 
| 47   void TranslateBack(TransLocation *loc) {} | 55   void TranslateBack(TransLocation *loc) {} | 
| 48 }; | 56 }; | 
| 49 | 57 | 
| 50 class WasmTranslation::TranslatorImpl::DisassemblingTranslator | 58 class WasmTranslation::TranslatorImpl::DisassemblingTranslator | 
| 51     : public WasmTranslation::TranslatorImpl { | 59     : public WasmTranslation::TranslatorImpl { | 
| 52   using OffsetTable = debug::WasmDisassembly::OffsetTable; | 60   using OffsetTable = debug::WasmDisassembly::OffsetTable; | 
| 53 | 61 | 
| 54  public: | 62  public: | 
| 55   DisassemblingTranslator(Isolate *isolate, Local<debug::WasmScript> script, | 63   DisassemblingTranslator(Isolate* isolate, Local<debug::WasmScript> script, | 
| 56                           WasmTranslation *translation, | 64                           WasmTranslation* translation, | 
| 57                           V8DebuggerAgentImpl *agent) | 65                           V8DebuggerAgentImpl* agent) | 
| 58       : script_(isolate, script) { | 66       : TranslatorImpl(translation, script->Id()), script_(isolate, script) { | 
| 59     // Register fake scripts for each function in this wasm module/script. | 67     // Register fake scripts for each function in this wasm module/script. | 
| 60     int num_functions = script->NumFunctions(); | 68     int num_functions = script->NumFunctions(); | 
| 61     int num_imported_functions = script->NumImportedFunctions(); | 69     int num_imported_functions = script->NumImportedFunctions(); | 
| 62     DCHECK_LE(0, num_imported_functions); | 70     DCHECK_LE(0, num_imported_functions); | 
| 63     DCHECK_LE(0, num_functions); | 71     DCHECK_LE(0, num_functions); | 
| 64     DCHECK_GE(num_functions, num_imported_functions); | 72     DCHECK_GE(num_functions, num_imported_functions); | 
| 65     String16 script_id = String16::fromInteger(script->Id()); | 73     String16 script_id = String16::fromInteger(script->Id()); | 
| 66     for (int func_idx = num_imported_functions; func_idx < num_functions; | 74     for (int func_idx = num_imported_functions; func_idx < num_functions; | 
| 67          ++func_idx) { | 75          ++func_idx) { | 
| 68       AddFakeScript(isolate, script_id, func_idx, translation, agent); | 76       AddFakeScript(isolate, script_id, func_idx, translation, agent); | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 94       loc->line = 0; | 102       loc->line = 0; | 
| 95       loc->column = 0; | 103       loc->column = 0; | 
| 96     } | 104     } | 
| 97   } | 105   } | 
| 98 | 106 | 
| 99   void TranslateBack(TransLocation *loc) { | 107   void TranslateBack(TransLocation *loc) { | 
| 100     int func_index = GetFunctionIndexFromFakeScriptId(loc->script_id); | 108     int func_index = GetFunctionIndexFromFakeScriptId(loc->script_id); | 
| 101     const OffsetTable *reverse_table = GetReverseTable(func_index); | 109     const OffsetTable *reverse_table = GetReverseTable(func_index); | 
| 102     if (!reverse_table) return; | 110     if (!reverse_table) return; | 
| 103     DCHECK(!reverse_table->empty()); | 111     DCHECK(!reverse_table->empty()); | 
|  | 112     v8::Isolate* isolate = loc->translation->isolate_; | 
| 104 | 113 | 
| 105     // Binary search for the given line and column. | 114     // Binary search for the given line and column. | 
| 106     unsigned left = 0;                                              // inclusive | 115     unsigned left = 0;                                              // inclusive | 
| 107     unsigned right = static_cast<unsigned>(reverse_table->size());  // exclusive | 116     unsigned right = static_cast<unsigned>(reverse_table->size());  // exclusive | 
| 108     while (right - left > 1) { | 117     while (right - left > 1) { | 
| 109       unsigned mid = (left + right) / 2; | 118       unsigned mid = (left + right) / 2; | 
| 110       auto &entry = (*reverse_table)[mid]; | 119       auto &entry = (*reverse_table)[mid]; | 
| 111       if (entry.line < loc->line || | 120       if (entry.line < loc->line || | 
| 112           (entry.line == loc->line && entry.column <= loc->column)) { | 121           (entry.line == loc->line && entry.column <= loc->column)) { | 
| 113         left = mid; | 122         left = mid; | 
| 114       } else { | 123       } else { | 
| 115         right = mid; | 124         right = mid; | 
| 116       } | 125       } | 
| 117     } | 126     } | 
| 118 | 127 | 
| 119     int found_byte_offset = 0; | 128     int found_byte_offset = 0; | 
| 120     // If we found an exact match, use it. Otherwise check whether the next | 129     // If we found an exact match, use it. Otherwise check whether the next | 
| 121     // bigger entry is still in the same line. Report that one then. | 130     // bigger entry is still in the same line. Report that one then. | 
|  | 131     // Otherwise we might have hit the special case of pointing after the last | 
|  | 132     // line, which is translated to the end of the function (one byte after the | 
|  | 133     // last function byte). | 
| 122     if ((*reverse_table)[left].line == loc->line && | 134     if ((*reverse_table)[left].line == loc->line && | 
| 123         (*reverse_table)[left].column == loc->column) { | 135         (*reverse_table)[left].column == loc->column) { | 
| 124       found_byte_offset = (*reverse_table)[left].byte_offset; | 136       found_byte_offset = (*reverse_table)[left].byte_offset; | 
| 125     } else if (left + 1 < reverse_table->size() && | 137     } else if (left + 1 < reverse_table->size() && | 
| 126                (*reverse_table)[left + 1].line == loc->line) { | 138                (*reverse_table)[left + 1].line == loc->line) { | 
| 127       found_byte_offset = (*reverse_table)[left + 1].byte_offset; | 139       found_byte_offset = (*reverse_table)[left + 1].byte_offset; | 
|  | 140     } else if (left == reverse_table->size() - 1 && | 
|  | 141                (*reverse_table)[left].line == loc->line - 1 && | 
|  | 142                loc->column == 0) { | 
|  | 143       std::pair<int, int> func_range = | 
|  | 144           script_.Get(isolate)->GetFunctionRange(func_index); | 
|  | 145       DCHECK_LE(func_range.first, func_range.second); | 
|  | 146       found_byte_offset = func_range.second - func_range.first; | 
| 128     } | 147     } | 
| 129 | 148 | 
| 130     v8::Isolate *isolate = loc->translation->isolate_; |  | 
| 131     loc->script_id = String16::fromInteger(script_.Get(isolate)->Id()); | 149     loc->script_id = String16::fromInteger(script_.Get(isolate)->Id()); | 
| 132     loc->line = func_index; | 150     loc->line = func_index; | 
| 133     loc->column = found_byte_offset; | 151     loc->column = found_byte_offset; | 
| 134   } | 152   } | 
| 135 | 153 | 
| 136  private: | 154  private: | 
| 137   String16 GetFakeScriptUrl(v8::Isolate *isolate, int func_index) { | 155   String16 GetFakeScriptUrl(v8::Isolate *isolate, int func_index) { | 
| 138     Local<debug::WasmScript> script = script_.Get(isolate); | 156     Local<debug::WasmScript> script = script_.Get(isolate); | 
| 139     String16 script_name = toProtocolString(script->Name().ToLocalChecked()); | 157     String16 script_name = toProtocolString(script->Name().ToLocalChecked()); | 
| 140     int numFunctions = script->NumFunctions(); | 158     int numFunctions = script->NumFunctions(); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 170     v8::Local<debug::WasmScript> script = script_.Get(isolate); | 188     v8::Local<debug::WasmScript> script = script_.Get(isolate); | 
| 171     // TODO(clemensh): Generate disassembly lazily when queried by the frontend. | 189     // TODO(clemensh): Generate disassembly lazily when queried by the frontend. | 
| 172     debug::WasmDisassembly disassembly = script->DisassembleFunction(func_idx); | 190     debug::WasmDisassembly disassembly = script->DisassembleFunction(func_idx); | 
| 173 | 191 | 
| 174     DCHECK_EQ(0, offset_tables_.count(func_idx)); | 192     DCHECK_EQ(0, offset_tables_.count(func_idx)); | 
| 175     offset_tables_.insert( | 193     offset_tables_.insert( | 
| 176         std::make_pair(func_idx, std::move(disassembly.offset_table))); | 194         std::make_pair(func_idx, std::move(disassembly.offset_table))); | 
| 177     String16 source(disassembly.disassembly.data(), | 195     String16 source(disassembly.disassembly.data(), | 
| 178                     disassembly.disassembly.length()); | 196                     disassembly.disassembly.length()); | 
| 179     std::unique_ptr<V8DebuggerScript> fake_script = | 197     std::unique_ptr<V8DebuggerScript> fake_script = | 
| 180         V8DebuggerScript::CreateWasm(isolate, script, fake_script_id, | 198         V8DebuggerScript::CreateWasm(isolate, translation, script, | 
| 181                                      std::move(fake_script_url), source); | 199                                      fake_script_id, std::move(fake_script_url), | 
|  | 200                                      source); | 
| 182 | 201 | 
| 183     translation->AddFakeScript(fake_script->scriptId(), this); | 202     translation->AddFakeScript(fake_script->scriptId(), this); | 
| 184     agent->didParseSource(std::move(fake_script), true); | 203     agent->didParseSource(std::move(fake_script), true); | 
| 185   } | 204   } | 
| 186 | 205 | 
| 187   int GetFunctionIndexFromFakeScriptId(const String16 &fake_script_id) { | 206   int GetFunctionIndexFromFakeScriptId(const String16 &fake_script_id) { | 
| 188     size_t last_dash_pos = fake_script_id.reverseFind('-'); | 207     size_t last_dash_pos = fake_script_id.reverseFind('-'); | 
| 189     DCHECK_GT(fake_script_id.length(), last_dash_pos); | 208     DCHECK_GT(fake_script_id.length(), last_dash_pos); | 
| 190     bool ok = true; | 209     bool ok = true; | 
| 191     int func_index = fake_script_id.substring(last_dash_pos + 1).toInteger(&ok); | 210     int func_index = fake_script_id.substring(last_dash_pos + 1).toInteger(&ok); | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 233   std::unordered_map<int, const OffsetTable> reverse_tables_; | 252   std::unordered_map<int, const OffsetTable> reverse_tables_; | 
| 234 }; | 253 }; | 
| 235 | 254 | 
| 236 WasmTranslation::WasmTranslation(v8::Isolate *isolate) | 255 WasmTranslation::WasmTranslation(v8::Isolate *isolate) | 
| 237     : isolate_(isolate), mode_(Disassemble) {} | 256     : isolate_(isolate), mode_(Disassemble) {} | 
| 238 | 257 | 
| 239 WasmTranslation::~WasmTranslation() { Clear(); } | 258 WasmTranslation::~WasmTranslation() { Clear(); } | 
| 240 | 259 | 
| 241 void WasmTranslation::AddScript(Local<debug::WasmScript> script, | 260 void WasmTranslation::AddScript(Local<debug::WasmScript> script, | 
| 242                                 V8DebuggerAgentImpl *agent) { | 261                                 V8DebuggerAgentImpl *agent) { | 
| 243   int script_id = script->Id(); | 262   // Instantiate new TranslatorImpls via new, the base class will register them | 
| 244   DCHECK_EQ(0, wasm_translators_.count(script_id)); | 263   // in wasm_translators_, taking ownership. This early registration is | 
| 245   std::unique_ptr<TranslatorImpl> impl; | 264   // necessary since the DisassemblingTranslator constructor already registers | 
|  | 265   // the fake scripts, which triggers setting breakpoints. | 
| 246   switch (mode_) { | 266   switch (mode_) { | 
| 247     case Raw: | 267     case Raw: | 
| 248       impl.reset(new TranslatorImpl::RawTranslator()); | 268       new TranslatorImpl::RawTranslator(this, script); | 
| 249       break; | 269       return; | 
| 250     case Disassemble: | 270     case Disassemble: | 
| 251       impl.reset(new TranslatorImpl::DisassemblingTranslator(isolate_, script, | 271       new TranslatorImpl::DisassemblingTranslator(isolate_, script, this, | 
| 252                                                              this, agent)); | 272                                                   agent); | 
| 253       break; | 273       return; | 
| 254   } | 274   } | 
| 255   DCHECK(impl); | 275   UNREACHABLE(); | 
| 256   wasm_translators_.insert(std::make_pair(script_id, std::move(impl))); |  | 
| 257 } | 276 } | 
| 258 | 277 | 
| 259 void WasmTranslation::Clear() { | 278 void WasmTranslation::Clear() { | 
| 260   wasm_translators_.clear(); | 279   wasm_translators_.clear(); | 
| 261   fake_scripts_.clear(); | 280   fake_scripts_.clear(); | 
| 262 } | 281 } | 
| 263 | 282 | 
| 264 // Translation "forward" (to artificial scripts). | 283 // Translation "forward" (to artificial scripts). | 
| 265 bool WasmTranslation::TranslateWasmScriptLocationToProtocolLocation( | 284 bool WasmTranslation::TranslateWasmScriptLocationToProtocolLocation( | 
| 266     String16 *script_id, int *line_number, int *column_number) { | 285     String16 *script_id, int *line_number, int *column_number) { | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 300   *column_number = trans_loc.column; | 319   *column_number = trans_loc.column; | 
| 301 | 320 | 
| 302   return true; | 321   return true; | 
| 303 } | 322 } | 
| 304 | 323 | 
| 305 void WasmTranslation::AddFakeScript(const String16 &scriptId, | 324 void WasmTranslation::AddFakeScript(const String16 &scriptId, | 
| 306                                     TranslatorImpl *translator) { | 325                                     TranslatorImpl *translator) { | 
| 307   DCHECK_EQ(0, fake_scripts_.count(scriptId)); | 326   DCHECK_EQ(0, fake_scripts_.count(scriptId)); | 
| 308   fake_scripts_.insert(std::make_pair(scriptId, translator)); | 327   fake_scripts_.insert(std::make_pair(scriptId, translator)); | 
| 309 } | 328 } | 
| OLD | NEW | 
|---|