diff --git a/BUILD.gn b/BUILD.gn index 7ac7293c0f..eb2b1113ea 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1493,6 +1493,8 @@ v8_source_set("v8_base") { "src/code-events.h", "src/code-factory.cc", "src/code-factory.h", + "src/code-reference.cc", + "src/code-reference.h", "src/code-stub-assembler.cc", "src/code-stub-assembler.h", "src/code-stubs-utils.h", diff --git a/src/assembler.cc b/src/assembler.cc index efe857175e..59d280a5ef 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -96,7 +96,7 @@ void AssemblerBase::FlushICache(void* start, size_t size) { void AssemblerBase::Print(Isolate* isolate) { OFStream os(stdout); - v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_, nullptr); + v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_); } // ----------------------------------------------------------------------------- @@ -457,12 +457,24 @@ RelocIterator::RelocIterator(Code* code, int mode_mask) rinfo_.data_ = 0; rinfo_.constant_pool_ = code->constant_pool(); // Relocation info is read backwards. - pos_ = code->relocation_start() + code->relocation_size(); + pos_ = code->relocation_end(); end_ = code->relocation_start(); if (mode_mask_ == 0) pos_ = end_; next(); } +RelocIterator::RelocIterator(const CodeReference code_reference, int mode_mask) + : mode_mask_(mode_mask) { + rinfo_.pc_ = code_reference.instruction_start(); + rinfo_.data_ = 0; + rinfo_.constant_pool_ = code_reference.constant_pool(); + // Relocation info is read backwards. + pos_ = code_reference.relocation_end(); + end_ = code_reference.relocation_start(); + if (mode_mask_ == 0) pos_ = end_; + next(); +} + RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) : mode_mask_(mode_mask) { rinfo_.pc_ = reinterpret_cast
(desc.buffer); diff --git a/src/assembler.h b/src/assembler.h index 6a6750888b..0f8de8d0d1 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -40,6 +40,7 @@ #include #include "src/allocation.h" +#include "src/code-reference.h" #include "src/contexts.h" #include "src/deoptimize-reason.h" #include "src/double.h" @@ -686,6 +687,8 @@ class RelocIterator: public Malloced { // iteration iff bit k of mode_mask is set. explicit RelocIterator(Code* code, int mode_mask = -1); explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1); + explicit RelocIterator(const CodeReference code_reference, + int mode_mask = -1); explicit RelocIterator(Vector instructions, Vector reloc_info, Address const_pool, int mode_mask = -1); diff --git a/src/code-reference.cc b/src/code-reference.cc new file mode 100644 index 0000000000..8d74cd256e --- /dev/null +++ b/src/code-reference.cc @@ -0,0 +1,53 @@ +// Copyright 2018 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/code-reference.h" + +#include "src/handles-inl.h" +#include "src/objects-inl.h" +#include "src/wasm/wasm-code-manager.h" + +namespace v8 { +namespace internal { + +Address CodeReference::constant_pool() const { + return kind == JS ? code.js->constant_pool() : code.wasm->constant_pool(); +} + +Address CodeReference::instruction_start() const { + return kind == JS + ? code.js->InstructionStart() + : reinterpret_cast
(code.wasm->instructions().start()); +} + +Address CodeReference::instruction_end() const { + return kind == JS + ? code.js->InstructionEnd() + : reinterpret_cast
(code.wasm->instructions().start() + + code.wasm->instructions().size()); +} + +int CodeReference::instruction_size() const { + return kind == JS ? code.js->InstructionSize() + : code.wasm->instructions().length(); +} + +const byte* CodeReference::relocation_start() const { + return kind == JS ? code.js->relocation_start() + : code.wasm->reloc_info().start(); +} + +const byte* CodeReference::relocation_end() const { + return kind == JS ? code.js->relocation_end() + : code.wasm->reloc_info().start() + + code.wasm->reloc_info().length(); +} + +int CodeReference::relocation_size() const { + return kind == JS ? code.js->relocation_size() + : code.wasm->reloc_info().length(); +} + +} // namespace internal +} // namespace v8 diff --git a/src/code-reference.h b/src/code-reference.h new file mode 100644 index 0000000000..a115dfebb6 --- /dev/null +++ b/src/code-reference.h @@ -0,0 +1,53 @@ +// Copyright 2018 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. + +#ifndef V8_CODE_REFERENCE_H_ +#define V8_CODE_REFERENCE_H_ + +#include "src/handles.h" +#include "src/objects.h" + +namespace v8 { +namespace internal { + +class Code; + +namespace wasm { +class WasmCode; +} + +struct CodeReference { + explicit CodeReference(const wasm::WasmCode* wasm_code = nullptr) + : kind(WASM), code(wasm_code) {} + explicit CodeReference(Handle js_code) : kind(JS), code(js_code) {} + + Address constant_pool() const; + Address instruction_start() const; + Address instruction_end() const; + int instruction_size() const; + const byte* relocation_start() const; + const byte* relocation_end() const; + int relocation_size() const; + bool is_null() const { + return kind == JS ? code.js.is_null() : code.wasm == nullptr; + } + + private: + enum { JS, WASM } kind; + union CodeUnion { + explicit CodeUnion(Handle js_code) : js(js_code) {} + explicit CodeUnion(const wasm::WasmCode* wasm_code) : wasm(wasm_code) {} + CodeUnion() : wasm(nullptr) {} + + const wasm::WasmCode* wasm; + Handle js; + } code; + + DISALLOW_NEW_AND_DELETE() +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_CODE_REFERENCE_H_ diff --git a/src/disassembler.cc b/src/disassembler.cc index 5ca09c7928..257ce92ec9 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -8,6 +8,7 @@ #include #include "src/assembler-inl.h" +#include "src/code-reference.h" #include "src/code-stubs.h" #include "src/debug/debug.h" #include "src/deoptimizer.h" @@ -27,22 +28,28 @@ namespace internal { class V8NameConverter: public disasm::NameConverter { public: - explicit V8NameConverter(Code* code) : code_(code) {} + explicit V8NameConverter(Code* code) + : isolate_(code->GetIsolate()), code_(CodeReference(handle(code))) {} + V8NameConverter(Isolate* isolate, const wasm::WasmCode* code) + : isolate_(isolate), code_(CodeReference(code)) {} + explicit V8NameConverter(Isolate* isolate) + : isolate_(isolate), code_(CodeReference()) {} virtual const char* NameOfAddress(byte* pc) const; virtual const char* NameInCode(byte* addr) const; - Code* code() const { return code_; } + const CodeReference& code() const { return code_; } + private: - Code* code_; + Isolate* isolate_; + CodeReference code_; EmbeddedVector v8_buffer_; }; const char* V8NameConverter::NameOfAddress(byte* pc) const { - if (code_ != nullptr) { - Isolate* isolate = code_->GetIsolate(); + if (!code_.is_null()) { const char* name = - isolate->builtins()->Lookup(reinterpret_cast
(pc)); + isolate_->builtins()->Lookup(reinterpret_cast
(pc)); if (name != nullptr) { SNPrintF(v8_buffer_, "%p (%s)", static_cast(pc), name); @@ -50,19 +57,19 @@ const char* V8NameConverter::NameOfAddress(byte* pc) const { } int offs = static_cast(reinterpret_cast
(pc) - - code_->raw_instruction_start()); + code_.instruction_start()); // print as code offset, if it seems reasonable - if (0 <= offs && offs < code_->raw_instruction_size()) { + if (0 <= offs && offs < code_.instruction_size()) { SNPrintF(v8_buffer_, "%p <+0x%x>", static_cast(pc), offs); return v8_buffer_.start(); } wasm::WasmCode* wasm_code = - isolate->wasm_engine()->code_manager()->LookupCode( + isolate_->wasm_engine()->code_manager()->LookupCode( reinterpret_cast
(pc)); if (wasm_code != nullptr) { SNPrintF(v8_buffer_, "%p (%s)", static_cast(pc), - GetWasmCodeKindAsString(wasm_code->kind())); + wasm::GetWasmCodeKindAsString(wasm_code->kind())); return v8_buffer_.start(); } } @@ -74,7 +81,7 @@ const char* V8NameConverter::NameOfAddress(byte* pc) const { const char* V8NameConverter::NameInCode(byte* addr) const { // The V8NameConverter is used for well known code, so we can "safely" // dereference pointers in generated code. - return (code_ != nullptr) ? reinterpret_cast(addr) : ""; + return code_.is_null() ? "" : reinterpret_cast(addr); } @@ -127,21 +134,30 @@ static void PrintRelocInfo(StringBuilder* out, Isolate* isolate, out->AddFormatted(" ;; external reference (%s)", reference_name); } else if (RelocInfo::IsCodeTarget(rmode)) { out->AddFormatted(" ;; code:"); - Code* code = Code::GetCodeFromTargetAddress(relocinfo->target_address()); - Code::Kind kind = code->kind(); - if (kind == Code::STUB) { - // Get the STUB key and extract major and minor key. - uint32_t key = code->stub_key(); - uint32_t minor_key = CodeStub::MinorKeyFromKey(key); - CodeStub::Major major_key = CodeStub::GetMajorKey(code); - DCHECK(major_key == CodeStub::MajorKeyFromKey(key)); - out->AddFormatted(" %s, %s, ", Code::Kind2String(kind), - CodeStub::MajorName(major_key)); - out->AddFormatted("minor: %d", minor_key); - } else if (code->is_builtin()) { - out->AddFormatted(" Builtin::%s", Builtins::name(code->builtin_index())); + wasm::WasmCode* wasmCode = + isolate->wasm_engine()->code_manager()->LookupCode( + relocinfo->target_address()); + if (wasmCode) { + out->AddFormatted(" wasm(%s)", + wasm::GetWasmCodeKindAsString(wasmCode->kind())); } else { - out->AddFormatted(" %s", Code::Kind2String(kind)); + Code* code = Code::GetCodeFromTargetAddress(relocinfo->target_address()); + Code::Kind kind = code->kind(); + if (kind == Code::STUB) { + // Get the STUB key and extract major and minor key. + uint32_t key = code->stub_key(); + uint32_t minor_key = CodeStub::MinorKeyFromKey(key); + CodeStub::Major major_key = CodeStub::GetMajorKey(code); + DCHECK(major_key == CodeStub::MajorKeyFromKey(key)); + out->AddFormatted(" %s, %s, ", Code::Kind2String(kind), + CodeStub::MajorName(major_key)); + out->AddFormatted("minor: %d", minor_key); + } else if (code->is_builtin()) { + out->AddFormatted(" Builtin::%s", + Builtins::name(code->builtin_index())); + } else { + out->AddFormatted(" %s", Code::Kind2String(kind)); + } } } else if (RelocInfo::IsRuntimeEntry(rmode) && isolate->deoptimizer_data() != nullptr) { @@ -182,7 +198,7 @@ static int DecodeIt(Isolate* isolate, std::ostream* os, byte* pc = begin; disasm::Disassembler d(converter); RelocIterator* it = nullptr; - if (converter.code() != nullptr) { + if (!converter.code().is_null()) { it = new RelocIterator(converter.code()); } else { // No relocation information when printing code stubs. @@ -262,9 +278,10 @@ static int DecodeIt(Isolate* isolate, std::ostream* os, // Print all the reloc info for this instruction which are not comments. for (size_t i = 0; i < pcs.size(); i++) { // Put together the reloc info - Code* host = converter.code(); - RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], host); - relocinfo.set_constant_pool(host ? host->constant_pool() : kNullAddress); + const CodeReference& host = converter.code(); + RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], nullptr); + relocinfo.set_constant_pool(host.is_null() ? kNullAddress + : host.constant_pool()); bool first_reloc_info = (i == 0); PrintRelocInfo(&out, isolate, ref_encoder, os, &relocinfo, @@ -274,7 +291,7 @@ static int DecodeIt(Isolate* isolate, std::ostream* os, // If this is a constant pool load and we haven't found any RelocInfo // already, check if we can find some RelocInfo for the target address in // the constant pool. - if (pcs.empty() && converter.code() != nullptr) { + if (pcs.empty() && !converter.code().is_null()) { RelocInfo dummy_rinfo(reinterpret_cast
(prev_pc), RelocInfo::NONE, 0, nullptr); if (dummy_rinfo.IsInConstantPool()) { @@ -321,6 +338,13 @@ int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, return DecodeIt(isolate, os, v8NameConverter, begin, end, current_pc); } +int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, + byte* end, const wasm::WasmCode* code, + void* current_pc) { + V8NameConverter v8NameConverter(isolate, code); + return DecodeIt(isolate, os, v8NameConverter, begin, end, current_pc); +} + #else // ENABLE_DISASSEMBLER int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, diff --git a/src/disassembler.h b/src/disassembler.h index 51ed0bf196..8ac649840d 100644 --- a/src/disassembler.h +++ b/src/disassembler.h @@ -10,6 +10,10 @@ namespace v8 { namespace internal { +namespace wasm { +class WasmCode; +} + class Disassembler : public AllStatic { public: // Decode instructions in the the interval [begin, end) and print the @@ -18,6 +22,8 @@ class Disassembler : public AllStatic { // the code object is used for name resolution and may be null. static int Decode(Isolate* isolate, std::ostream* os, byte* begin, byte* end, Code* code = nullptr, void* current_pc = nullptr); + static int Decode(Isolate* isolate, std::ostream* os, byte* begin, byte* end, + const wasm::WasmCode* code, void* current_pc = nullptr); }; } // namespace internal diff --git a/src/objects/code-inl.h b/src/objects/code-inl.h index fba59190b8..ed5d7a7e2e 100644 --- a/src/objects/code-inl.h +++ b/src/objects/code-inl.h @@ -304,6 +304,11 @@ byte* Code::relocation_start() const { return unchecked_relocation_info()->GetDataStartAddress(); } +byte* Code::relocation_end() const { + return unchecked_relocation_info()->GetDataStartAddress() + + unchecked_relocation_info()->length(); +} + int Code::relocation_size() const { return unchecked_relocation_info()->length(); } diff --git a/src/objects/code.h b/src/objects/code.h index 5296110d69..a006b519c8 100644 --- a/src/objects/code.h +++ b/src/objects/code.h @@ -243,6 +243,9 @@ class Code : public HeapObject { // Returns the address of the first relocation info (read backwards!). inline byte* relocation_start() const; + // Returns the address right after the relocation info (read backwards!). + inline byte* relocation_end() const; + // [has_unwinding_info]: Whether this code object has unwinding information. // If it doesn't, unwinding_information_start() will point to invalid data. // diff --git a/src/wasm/wasm-code-manager.cc b/src/wasm/wasm-code-manager.cc index 600e9b2536..cd68332d44 100644 --- a/src/wasm/wasm-code-manager.cc +++ b/src/wasm/wasm-code-manager.cc @@ -255,7 +255,7 @@ void WasmCode::Disassemble(const char* name, Isolate* isolate, // TODO(mtrofin): rework the dependency on isolate and code in // Disassembler::Decode. Disassembler::Decode(isolate, &os, instructions().start(), - instructions().start() + instruction_size, nullptr); + instructions().start() + instruction_size, this); os << "\n"; if (!source_positions().is_empty()) {