[VM] Use X64 disassembler for IA32 and X64

R=vegorov@google.com

Bug:
Change-Id: I19b1f58e16ea35dc81b941c54e6e57b97cad3d74
Reviewed-on: https://dart-review.googlesource.com/22020
Commit-Queue: Erik Corry <erikcorry@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Erik Corry 2017-11-22 08:01:07 +00:00 committed by commit-bot@chromium.org
parent d22b6950c1
commit 9e42f006d9
11 changed files with 3861 additions and 2152 deletions

View file

@ -387,6 +387,18 @@ typedef simd128_value_t fpu_register_t;
#define Pu PRIuPTR
#define Px PRIxPTR
#define PX PRIXPTR
#define Pd8 PRId8
#define Pu8 PRIu8
#define Px8 PRIx8
#define PX8 PRIX8
#define Pd16 PRId16
#define Pu16 PRIu16
#define Px16 PRIx16
#define PX16 PRIX16
#define Pd32 PRId32
#define Pu32 PRIu32
#define Px32 PRIx32
#define PX32 PRIX32
#define Pd64 PRId64
#define Pu64 PRIu64
#define Px64 PRIx64

View file

@ -26,4 +26,22 @@ typedef unsigned __int64 uint64_t;
#define PRIx64 "I64x"
#define PRIX64 "I64X"
// Printf format specifiers for int32_t and uint32_t.
#define PRId32 "I32d"
#define PRIu32 "I32u"
#define PRIx32 "I32x"
#define PRIX32 "I32X"
// Printf format specifiers for int16_t and uint16_t.
#define PRId16 "I16d"
#define PRIu16 "I16u"
#define PRIx16 "I16x"
#define PRIX16 "I16X"
// Printf format specifiers for int8_t and uint8_t.
#define PRId8 "I8d"
#define PRIu8 "I8u"
#define PRIx8 "I8x"
#define PRIX8 "I8X"
#endif // RUNTIME_PLATFORM_INTTYPES_SUPPORT_WIN_H_

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -97,6 +97,47 @@ void DisassembleToJSONStream::Print(const char* format, ...) {
free(p);
}
#if !defined(PRODUCT)
void DisassembleToMemory::ConsumeInstruction(const Code& code,
char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
Object* object,
uword pc) {
intptr_t len = strlen(human_buffer);
if (remaining_ < len + 100) {
UNREACHABLE(); // Buffer too small.
}
memmove(buffer_, human_buffer, len);
buffer_ += len;
remaining_ -= len;
*buffer_++ = '\n';
remaining_--;
*buffer_ = '\0';
}
void DisassembleToMemory::Print(const char* format, ...) {
va_list args;
va_start(args, format);
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
va_end(args);
if (remaining_ < len + 100) {
UNREACHABLE(); // Buffer too small.
}
va_start(args, format);
intptr_t len2 = OS::VSNPrint(buffer_, len, format, args);
va_end(args);
ASSERT(len == len2);
buffer_ += len;
remaining_ -= len;
*buffer_++ = '\n';
remaining_--;
*buffer_ = '\0';
}
#endif
void Disassembler::Disassemble(uword start,
uword end,
DisassemblyFormatter* formatter,

View file

@ -81,6 +81,33 @@ class DisassembleToJSONStream : public DisassemblyFormatter {
DISALLOW_COPY_AND_ASSIGN(DisassembleToJSONStream);
};
#if !defined(PRODUCT)
// Basic disassembly formatter that outputs the disassembled instruction
// to a memory buffer. This is only intended for test writing.
class DisassembleToMemory : public DisassemblyFormatter {
public:
DisassembleToMemory(char* buffer, uintptr_t length)
: DisassemblyFormatter(), buffer_(buffer), remaining_(length) {}
~DisassembleToMemory() {}
virtual void ConsumeInstruction(const Code& code,
char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
Object* object,
uword pc);
virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
private:
char* buffer_;
int remaining_;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(DisassembleToMemory);
};
#endif
// Disassemble instructions.
class Disassembler : public AllStatic {
public:
@ -118,6 +145,19 @@ class Disassembler : public AllStatic {
#endif
}
static void Disassemble(uword start,
uword end,
char* buffer,
uintptr_t buffer_size) {
#if !defined(PRODUCT)
DisassembleToMemory memory_formatter(buffer, buffer_size);
LogBlock lb;
Disassemble(start, end, &memory_formatter);
#else
UNREACHABLE();
#endif
}
// Decodes one instruction.
// Writes a hexadecimal representation into the hex_buffer and a
// human-readable representation into the human_buffer.

File diff suppressed because it is too large Load diff

View file

@ -26,8 +26,7 @@ compiler_sources = [
"assembler/disassembler_arm.cc",
"assembler/disassembler_arm64.cc",
"assembler/disassembler_dbc.cc",
"assembler/disassembler_ia32.cc",
"assembler/disassembler_x64.cc",
"assembler/disassembler_x86.cc",
"backend/block_scheduler.cc",
"backend/block_scheduler.h",
"backend/branch_optimizer.cc",

View file

@ -550,6 +550,12 @@ char* TestCase::BigintToHexValue(Dart_CObject* bigint) {
return bin::CObject::BigintToHexValue(bigint);
}
#if !defined(PRODUCT)
static bool IsHex(int c) {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f');
}
#endif
void AssemblerTest::Assemble() {
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name_));
@ -571,14 +577,33 @@ void AssemblerTest::Assemble() {
code_.set_owner(function);
code_.set_exception_handlers(Object::empty_exception_handlers());
#ifndef PRODUCT
const Instructions& instructions = Instructions::Handle(code_.instructions());
uword start = instructions.PayloadStart();
if (FLAG_disassemble) {
OS::Print("Code for test '%s' {\n", name_);
const Instructions& instructions =
Instructions::Handle(code_.instructions());
uword start = instructions.PayloadStart();
Disassembler::Disassemble(start, start + assembler_->CodeSize());
OS::Print("}\n");
}
Disassembler::Disassemble(start, start + assembler_->CodeSize(), disassembly_,
DISASSEMBLY_SIZE);
// Blank out big hex constants, since they are not stable from run to run.
bool in_hex_constant = false;
for (char* p = disassembly_; *p != '\0'; p++) {
if (in_hex_constant) {
if (IsHex(*p)) {
*p = '.';
} else {
in_hex_constant = false;
}
} else {
if (*p == '0' && *(p + 1) == 'x' && IsHex(*(p + 2)) && IsHex(*(p + 3)) &&
IsHex(*(p + 4))) {
p++;
in_hex_constant = true;
}
}
}
#endif // !PRODUCT
}

View file

@ -414,6 +414,7 @@ class AssemblerTest {
const Code& code() const { return code_; }
uword payload_start() const { return code_.PayloadStart(); }
uword payload_size() const { return assembler_->CodeSize(); }
uword entry() const { return code_.UncheckedEntryPoint(); }
// Invoke/InvokeWithCodeAndThread is used to call assembler test functions
@ -524,10 +525,15 @@ class AssemblerTest {
// Assemble test and set code_.
void Assemble();
// Disassembly of the code with large constants blanked out.
char* BlankedDisassembly() { return disassembly_; }
private:
const char* name_;
Assembler* assembler_;
Code& code_;
static const intptr_t DISASSEMBLY_SIZE = 10240;
char disassembly_[DISASSEMBLY_SIZE];
DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
};