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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/inspector/wasm-translation.h ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/inspector/wasm-translation.cc
diff --git a/src/inspector/wasm-translation.cc b/src/inspector/wasm-translation.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0775460ae715f9b3bcfabcf539a0f7e77fa3938e
--- /dev/null
+++ b/src/inspector/wasm-translation.cc
@@ -0,0 +1,310 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/inspector/wasm-translation.h"
+
+#include <algorithm>
+
+#include "src/debug/debug-interface.h"
+#include "src/inspector/protocol/Debugger.h"
+#include "src/inspector/script-breakpoint.h"
+#include "src/inspector/string-util.h"
+#include "src/inspector/v8-debugger-agent-impl.h"
+#include "src/inspector/v8-debugger-script.h"
+#include "src/inspector/v8-debugger.h"
+#include "src/inspector/v8-inspector-impl.h"
+
+using namespace v8_inspector;
+using namespace v8;
+
+namespace {
+int GetScriptId(Isolate *isolate, Local<Object> script_wrapper) {
+ Local<Value> script_id = script_wrapper
+ ->Get(isolate->GetCurrentContext(),
+ toV8StringInternalized(isolate, "id"))
+ .ToLocalChecked();
+ DCHECK(script_id->IsInt32());
+ return script_id->Int32Value(isolate->GetCurrentContext()).FromJust();
+}
+
+String16 GetScriptName(Isolate *isolate, Local<Object> script_wrapper) {
+ Local<Value> script_name = script_wrapper
+ ->Get(isolate->GetCurrentContext(),
+ toV8StringInternalized(isolate, "name"))
+ .ToLocalChecked();
+ DCHECK(script_name->IsString());
+ return toProtocolString(script_name.As<String>());
+}
+
+} // namespace
+
+class WasmTranslation::TranslatorImpl {
+ public:
+ struct TransLocation {
+ WasmTranslation *translation;
+ String16 script_id;
+ int line;
+ int column;
+ int context_group_id;
+ TransLocation(WasmTranslation *translation, String16 script_id, int line,
+ int column, int context_group_id)
+ : translation(translation),
+ script_id(script_id),
+ line(line),
+ column(column),
+ context_group_id(context_group_id) {}
+ };
+
+ virtual void Translate(TransLocation *loc) = 0;
+ virtual void TranslateBack(TransLocation *loc) = 0;
+
+ class RawTranslator;
+ class DisassemblingTranslator;
+};
+
+class WasmTranslation::TranslatorImpl::RawTranslator
+ : public WasmTranslation::TranslatorImpl {
+ public:
+ void Translate(TransLocation *loc) {}
+ void TranslateBack(TransLocation *loc) {}
+};
+
+class WasmTranslation::TranslatorImpl::DisassemblingTranslator
+ : public WasmTranslation::TranslatorImpl {
+ using OffsetTable = std::vector<std::tuple<uint32_t, int, int>>;
+
+ public:
+ DisassemblingTranslator(Isolate *isolate, Local<Object> script)
+ : script_(isolate, script) {}
+
+ void Translate(TransLocation *loc) {
+ const OffsetTable &offset_table = GetOffsetTable(loc);
+ DCHECK(!offset_table.empty());
+ uint32_t byte_offset = static_cast<uint32_t>(loc->column);
+
+ // Binary search for the given offset.
+ unsigned left = 0; // inclusive
+ unsigned right = static_cast<unsigned>(offset_table.size()); // exclusive
+ while (right - left > 1) {
+ unsigned mid = (left + right) / 2;
+ if (std::get<0>(offset_table[mid]) <= byte_offset) {
+ left = mid;
+ } else {
+ right = mid;
+ }
+ }
+
+ loc->script_id = GetFakeScriptId(loc);
+ if (std::get<0>(offset_table[left]) == byte_offset) {
+ loc->line = std::get<1>(offset_table[left]);
+ loc->column = std::get<2>(offset_table[left]);
+ } else {
+ loc->line = 0;
+ loc->column = 0;
+ }
+ }
+
+ void TranslateBack(TransLocation *loc) {
+ int func_index = GetFunctionIndexFromFakeScriptId(loc->script_id);
+ const OffsetTable *reverse_table = GetReverseTable(func_index);
+ if (!reverse_table) return;
+ DCHECK(!reverse_table->empty());
+
+ // Binary search for the given line and column.
+ unsigned left = 0; // inclusive
+ unsigned right = static_cast<unsigned>(reverse_table->size()); // exclusive
+ while (right - left > 1) {
+ unsigned mid = (left + right) / 2;
+ auto &entry = (*reverse_table)[mid];
+ if (std::get<1>(entry) < loc->line ||
+ (std::get<1>(entry) == loc->line &&
+ std::get<2>(entry) <= loc->column)) {
+ left = mid;
+ } else {
+ right = mid;
+ }
+ }
+
+ int found_byte_offset = 0;
+ // If we found an exact match, use it. Otherwise check whether the next
+ // bigger entry is still in the same line. Report that one then.
+ if (std::get<1>((*reverse_table)[left]) == loc->line &&
+ std::get<2>((*reverse_table)[left]) == loc->column) {
+ found_byte_offset = std::get<0>((*reverse_table)[left]);
+ } else if (left + 1 < reverse_table->size() &&
+ std::get<1>((*reverse_table)[left + 1]) == loc->line) {
+ found_byte_offset = std::get<0>((*reverse_table)[left + 1]);
+ }
+
+ v8::Isolate *isolate = loc->translation->isolate_;
+ loc->script_id =
+ String16::fromInteger(GetScriptId(isolate, script_.Get(isolate)));
+ loc->line = func_index;
+ loc->column = found_byte_offset;
+ }
+
+ private:
+ String16 GetFakeScriptUrl(const TransLocation *loc) {
+ v8::Isolate *isolate = loc->translation->isolate_;
+ String16 script_name = GetScriptName(isolate, script_.Get(isolate));
+ return String16::concat("wasm://wasm/", script_name, '/', script_name, '-',
+ String16::fromInteger(loc->line));
+ }
+
+ String16 GetFakeScriptId(const TransLocation *loc) {
+ return String16::concat(loc->script_id, '-',
+ String16::fromInteger(loc->line));
+ }
+
+ int GetFunctionIndexFromFakeScriptId(const String16 &fake_script_id) {
+ size_t last_dash_pos = fake_script_id.reverseFind('-');
+ DCHECK_GT(fake_script_id.length(), last_dash_pos);
+ bool ok = true;
+ int func_index = fake_script_id.substring(last_dash_pos + 1).toInteger(&ok);
+ DCHECK(ok);
+ return func_index;
+ }
+
+ const OffsetTable &GetOffsetTable(const TransLocation *loc) {
+ int func_index = loc->line;
+ auto it = offset_tables_.find(func_index);
+ if (it != offset_tables_.end()) return it->second;
+
+ v8::Isolate *isolate = loc->translation->isolate_;
+ std::pair<std::string, OffsetTable> disassembly =
+ DebugInterface::DisassembleWasmFunction(isolate, script_.Get(isolate),
+ func_index);
+
+ it = offset_tables_
+ .insert(std::make_pair(func_index, std::move(disassembly.second)))
+ .first;
+
+ String16 fake_script_id = GetFakeScriptId(loc);
+ String16 fake_script_url = GetFakeScriptUrl(loc);
+ String16 source(disassembly.first.data(), disassembly.first.length());
+ std::unique_ptr<V8DebuggerScript> fake_script(new V8DebuggerScript(
+ fake_script_id, std::move(fake_script_url), source));
+
+ loc->translation->AddFakeScript(std::move(fake_script), this,
+ loc->context_group_id);
+
+ return it->second;
+ }
+
+ const OffsetTable *GetReverseTable(int func_index) {
+ auto it = reverse_tables_.find(func_index);
+ if (it != reverse_tables_.end()) return &it->second;
+
+ // Find offset table, copy and sort it to get reverse table.
+ it = offset_tables_.find(func_index);
+ if (it == offset_tables_.end()) return nullptr;
+
+ OffsetTable reverse_table = it->second;
+ // Order by line, column, then byte offset.
+ auto cmp = [](std::tuple<uint32_t, int, int> el1,
+ std::tuple<uint32_t, int, int> el2) {
+ if (std::get<1>(el1) != std::get<1>(el2))
+ return std::get<1>(el1) < std::get<1>(el2);
+ if (std::get<2>(el1) != std::get<2>(el2))
+ return std::get<2>(el1) < std::get<2>(el2);
+ return std::get<0>(el1) < std::get<0>(el2);
+ };
+ std::sort(reverse_table.begin(), reverse_table.end(), cmp);
+
+ auto inserted = reverse_tables_.insert(
+ std::make_pair(func_index, std::move(reverse_table)));
+ DCHECK(inserted.second);
+ return &inserted.first->second;
+ }
+
+ Global<Object> script_;
+
+ // We assume to only disassemble a subset of the functions, so store them in a
+ // map instead of an array.
+ std::unordered_map<int, const OffsetTable> offset_tables_;
+ std::unordered_map<int, const OffsetTable> reverse_tables_;
+};
+
+WasmTranslation::WasmTranslation(v8::Isolate *isolate, V8Debugger *debugger)
+ : isolate_(isolate), debugger_(debugger), mode_(Disassemble) {}
+
+WasmTranslation::~WasmTranslation() { Clear(); }
+
+void WasmTranslation::AddScript(Local<Object> script_wrapper) {
+ int script_id = GetScriptId(isolate_, script_wrapper);
+ DCHECK_EQ(0U, wasm_translators_.count(script_id));
+ std::unique_ptr<TranslatorImpl> impl;
+ switch (mode_) {
+ case Raw:
+ impl.reset(new TranslatorImpl::RawTranslator());
+ break;
+ case Disassemble:
+ impl.reset(new TranslatorImpl::DisassemblingTranslator(isolate_,
+ script_wrapper));
+ break;
+ }
+ DCHECK(impl);
+ wasm_translators_.insert(std::make_pair(script_id, std::move(impl)));
+}
+
+void WasmTranslation::Clear() {
+ wasm_translators_.clear();
+ fake_scripts_.clear();
+}
+
+// Translation "forward" (to artificial scripts).
+bool WasmTranslation::TranslateWasmScriptLocationToProtocolLocation(
+ String16 *script_id, int *line_number, int *column_number,
+ int context_group_id) {
+ DCHECK(script_id && line_number && column_number);
+ bool ok = true;
+ int script_id_int = script_id->toInteger(&ok);
+ if (!ok) return false;
+
+ auto it = wasm_translators_.find(script_id_int);
+ if (it == wasm_translators_.end()) return false;
+ TranslatorImpl *translator = it->second.get();
+
+ TranslatorImpl::TransLocation trans_loc(this, std::move(*script_id),
+ *line_number, *column_number,
+ context_group_id);
+ translator->Translate(&trans_loc);
+
+ *script_id = std::move(trans_loc.script_id);
+ *line_number = trans_loc.line;
+ *column_number = trans_loc.column;
+
+ return true;
+}
+
+// Translation "backward" (from artificial to real scripts).
+bool WasmTranslation::TranslateProtocolLocationToWasmScriptLocation(
+ String16 *script_id, int *line_number, int *column_number) {
+ auto it = fake_scripts_.find(*script_id);
+ if (it == fake_scripts_.end()) return false;
+ TranslatorImpl *translator = it->second;
+
+ TranslatorImpl::TransLocation trans_loc(this, std::move(*script_id),
+ *line_number, *column_number, -1);
+ translator->TranslateBack(&trans_loc);
+
+ *script_id = std::move(trans_loc.script_id);
+ *line_number = trans_loc.line;
+ *column_number = trans_loc.column;
+
+ return true;
+}
+
+void WasmTranslation::AddFakeScript(
+ std::unique_ptr<V8DebuggerScript> fake_script, TranslatorImpl *translator,
+ int context_group_id) {
+ bool inserted =
+ fake_scripts_.insert(std::make_pair(fake_script->scriptId(), translator))
+ .second;
+ DCHECK(inserted);
+ USE(inserted);
+ V8DebuggerAgentImpl *agent =
+ debugger_->inspector()->enabledDebuggerAgentForGroup(context_group_id);
+ agent->didParseSource(std::move(fake_script), true);
+}
« 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