Reland "Introduce CodeReference"
This is a reland of 4d7ad46db4
Original change's description:
> Introduce CodeReference
>
> Add a struct CodeReference that can be stack allocated to pass a
> reference to either an on-heap code object or off-heap WasmCode object
> in a gc safe manner. The struct also provides a common interface such
> that code can be written independently of the kind of code object it
> references.
>
> Change-Id: I5a6f74462e6e141d167c7fd9bac8c21941fd83b1
> Reviewed-on: https://chromium-review.googlesource.com/977905
> Commit-Queue: Stephan Herhut <herhut@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#52580}
Change-Id: I40861474fe4a3efd72e6c59e2e7b847ab6772735
Reviewed-on: https://chromium-review.googlesource.com/1013939
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52665}
This commit is contained in:
parent
1c38f9be85
commit
9a200cd2b4
2
BUILD.gn
2
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",
|
||||
|
@ -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<Address>(desc.buffer);
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <map>
|
||||
|
||||
#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<byte> instructions,
|
||||
Vector<const byte> reloc_info, Address const_pool,
|
||||
int mode_mask = -1);
|
||||
|
53
src/code-reference.cc
Normal file
53
src/code-reference.cc
Normal file
@ -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<Address>(code.wasm->instructions().start());
|
||||
}
|
||||
|
||||
Address CodeReference::instruction_end() const {
|
||||
return kind == JS
|
||||
? code.js->InstructionEnd()
|
||||
: reinterpret_cast<Address>(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
|
53
src/code-reference.h
Normal file
53
src/code-reference.h
Normal file
@ -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<Code> 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<Code> js_code) : js(js_code) {}
|
||||
explicit CodeUnion(const wasm::WasmCode* wasm_code) : wasm(wasm_code) {}
|
||||
CodeUnion() : wasm(nullptr) {}
|
||||
|
||||
const wasm::WasmCode* wasm;
|
||||
Handle<Code> js;
|
||||
} code;
|
||||
|
||||
DISALLOW_NEW_AND_DELETE()
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODE_REFERENCE_H_
|
@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#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<char, 128> 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<Address>(pc));
|
||||
isolate_->builtins()->Lookup(reinterpret_cast<Address>(pc));
|
||||
|
||||
if (name != nullptr) {
|
||||
SNPrintF(v8_buffer_, "%p (%s)", static_cast<void*>(pc), name);
|
||||
@ -50,19 +57,19 @@ const char* V8NameConverter::NameOfAddress(byte* pc) const {
|
||||
}
|
||||
|
||||
int offs = static_cast<int>(reinterpret_cast<Address>(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<void*>(pc), offs);
|
||||
return v8_buffer_.start();
|
||||
}
|
||||
|
||||
wasm::WasmCode* wasm_code =
|
||||
isolate->wasm_engine()->code_manager()->LookupCode(
|
||||
isolate_->wasm_engine()->code_manager()->LookupCode(
|
||||
reinterpret_cast<Address>(pc));
|
||||
if (wasm_code != nullptr) {
|
||||
SNPrintF(v8_buffer_, "%p (%s)", static_cast<void*>(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<const char*>(addr) : "";
|
||||
return code_.is_null() ? "" : reinterpret_cast<const char*>(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<Address>(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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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()) {
|
||||
|
Loading…
Reference in New Issue
Block a user