Commit 6cc1fffc authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[mksnapshot] Refactor platform-specific WriteByteChunk

This moves the platform-specific WriteByteChunk (& friends) into
platform-specific embedded file writers.

Bug: v8:9103
Change-Id: I0113c90dbf661a39dabe62b420cf6a160ee1be1d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1631412
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61852}
parent 8c5d0e65
......@@ -123,70 +123,6 @@ int WriteDirectiveOrSeparator(PlatformEmbeddedFileWriterBase* w,
return current_line_length + printed_chars;
}
#if defined(_MSC_VER) && !defined(__clang__)
#define V8_COMPILER_IS_MSVC
#endif
// TODO(jgruber): Move these sections into platform-dependent file writers.
#if defined(V8_COMPILER_IS_MSVC)
// Windows MASM doesn't have an .octa directive, use QWORDs instead.
// Note: MASM *really* does not like large data streams. It takes over 5
// minutes to assemble the ~350K lines of embedded.S produced when using
// BYTE directives in a debug build. QWORD produces roughly 120KLOC and
// reduces assembly time to ~40 seconds. Still terrible, but much better
// than before. See also: https://crbug.com/v8/8475.
static constexpr DataDirective kByteChunkDirective = kQuad;
static constexpr int kByteChunkSize = 8;
int WriteByteChunk(PlatformEmbeddedFileWriterBase* w, int current_line_length,
const uint8_t* data) {
const uint64_t* quad_ptr = reinterpret_cast<const uint64_t*>(data);
return current_line_length + w->HexLiteral(*quad_ptr);
}
#elif defined(V8_OS_AIX)
// PPC uses a fixed 4 byte instruction set, using .long
// to prevent any unnecessary padding.
static constexpr DataDirective kByteChunkDirective = kLong;
static constexpr int kByteChunkSize = 4;
int WriteByteChunk(PlatformEmbeddedFileWriterBase* w, int current_line_length,
const uint8_t* data) {
const uint32_t* long_ptr = reinterpret_cast<const uint32_t*>(data);
return current_line_length + w->HexLiteral(*long_ptr);
}
#else // defined(V8_COMPILER_IS_MSVC) || defined(V8_OS_AIX)
static constexpr DataDirective kByteChunkDirective = kOcta;
static constexpr int kByteChunkSize = 16;
int WriteByteChunk(PlatformEmbeddedFileWriterBase* w, int current_line_length,
const uint8_t* data) {
const size_t size = kInt64Size;
uint64_t part1, part2;
// Use memcpy for the reads since {data} is not guaranteed to be aligned.
#ifdef V8_TARGET_BIG_ENDIAN
memcpy(&part1, data, size);
memcpy(&part2, data + size, size);
#else
memcpy(&part1, data + size, size);
memcpy(&part2, data, size);
#endif // V8_TARGET_BIG_ENDIAN
if (part1 != 0) {
current_line_length +=
fprintf(w->fp(), "0x%" PRIx64 "%016" PRIx64, part1, part2);
} else {
current_line_length += fprintf(w->fp(), "0x%" PRIx64, part2);
}
return current_line_length;
}
#endif // defined(V8_COMPILER_IS_MSVC) || defined(V8_OS_AIX)
#undef V8_COMPILER_IS_MSVC
int WriteLineEndIfNeeded(PlatformEmbeddedFileWriterBase* w,
int current_line_length, int write_size) {
static const int kTextWidth = 100;
......@@ -210,12 +146,14 @@ void EmbeddedFileWriter::WriteBinaryContentsAsInlineAssembly(
uint32_t i = 0;
// Begin by writing out byte chunks.
for (; i + kByteChunkSize < size; i += kByteChunkSize) {
const DataDirective directive = w->ByteChunkDataDirective();
const int byte_chunk_size = DataDirectiveSize(directive);
for (; i + byte_chunk_size < size; i += byte_chunk_size) {
current_line_length =
WriteDirectiveOrSeparator(w, current_line_length, kByteChunkDirective);
current_line_length = WriteByteChunk(w, current_line_length, data + i);
WriteDirectiveOrSeparator(w, current_line_length, directive);
current_line_length += w->WriteByteChunk(data + i);
current_line_length =
WriteLineEndIfNeeded(w, current_line_length, kByteChunkSize);
WriteLineEndIfNeeded(w, current_line_length, byte_chunk_size);
}
if (current_line_length != 0) w->Newline();
current_line_length = 0;
......
......@@ -114,6 +114,18 @@ int PlatformEmbeddedFileWriterAIX::IndentedDataDirective(
return fprintf(fp_, " %s ", DirectiveAsString(directive));
}
DataDirective PlatformEmbeddedFileWriterAIX::ByteChunkDataDirective() const {
// PPC uses a fixed 4 byte instruction set, using .long
// to prevent any unnecessary padding.
return kLong;
}
int PlatformEmbeddedFileWriterAIX::WriteByteChunk(const uint8_t* data) {
DCHECK_EQ(ByteChunkDataDirective(), kLong);
const uint32_t* long_ptr = reinterpret_cast<const uint32_t*>(data);
return HexLiteral(*long_ptr);
}
#undef SYMBOL_PREFIX
} // namespace internal
......
......@@ -47,6 +47,9 @@ class PlatformEmbeddedFileWriterAIX : public PlatformEmbeddedFileWriterBase {
int IndentedDataDirective(DataDirective directive) override;
DataDirective ByteChunkDataDirective() const override;
int WriteByteChunk(const uint8_t* data) override;
private:
void DeclareSymbolGlobal(const char* name);
......
......@@ -24,6 +24,42 @@ DataDirective PointerSizeDirective() {
}
}
int DataDirectiveSize(DataDirective directive) {
switch (directive) {
case kByte:
return 1;
case kLong:
return 4;
case kQuad:
return 8;
case kOcta:
return 16;
}
UNREACHABLE();
}
int PlatformEmbeddedFileWriterBase::WriteByteChunk(const uint8_t* data) {
DCHECK_EQ(ByteChunkDataDirective(), kOcta);
static constexpr size_t kSize = kInt64Size;
uint64_t part1, part2;
// Use memcpy for the reads since {data} is not guaranteed to be aligned.
#ifdef V8_TARGET_BIG_ENDIAN
memcpy(&part1, data, kSize);
memcpy(&part2, data + kSize, kSize);
#else
memcpy(&part1, data + kSize, kSize);
memcpy(&part2, data, kSize);
#endif // V8_TARGET_BIG_ENDIAN
if (part1 != 0) {
return fprintf(fp(), "0x%" PRIx64 "%016" PRIx64, part1, part2);
} else {
return fprintf(fp(), "0x%" PRIx64, part2);
}
}
namespace {
EmbeddedTargetArch DefaultEmbeddedTargetArch() {
......
......@@ -22,6 +22,7 @@ enum DataDirective {
};
DataDirective PointerSizeDirective();
int DataDirectiveSize(DataDirective directive);
enum class EmbeddedTargetOs {
kAIX,
......@@ -77,6 +78,9 @@ class PlatformEmbeddedFileWriterBase {
virtual int IndentedDataDirective(DataDirective directive) = 0;
virtual DataDirective ByteChunkDataDirective() const { return kOcta; }
virtual int WriteByteChunk(const uint8_t* data);
// This awkward interface works around the fact that unwind data emission
// is both high-level and platform-dependent. The former implies it should
// live in EmbeddedFileWriter, but code there should be platform-independent.
......
......@@ -582,6 +582,30 @@ int PlatformEmbeddedFileWriterWin::IndentedDataDirective(
#endif
DataDirective PlatformEmbeddedFileWriterWin::ByteChunkDataDirective() const {
#if defined(V8_COMPILER_IS_MSVC)
// Windows MASM doesn't have an .octa directive, use QWORDs instead.
// Note: MASM *really* does not like large data streams. It takes over 5
// minutes to assemble the ~350K lines of embedded.S produced when using
// BYTE directives in a debug build. QWORD produces roughly 120KLOC and
// reduces assembly time to ~40 seconds. Still terrible, but much better
// than before. See also: https://crbug.com/v8/8475.
return kQuad;
#else
return PlatformEmbeddedFileWriterBase::ByteChunkDataDirective();
#endif
}
int PlatformEmbeddedFileWriterWin::WriteByteChunk(const uint8_t* data) {
#if defined(V8_COMPILER_IS_MSVC)
DCHECK_EQ(ByteChunkDataDirective(), kQuad);
const uint64_t* quad_ptr = reinterpret_cast<const uint64_t*>(data);
return HexLiteral(*quad_ptr);
#else
return PlatformEmbeddedFileWriterBase::WriteByteChunk(data);
#endif
}
#undef SYMBOL_PREFIX
#undef V8_ASSEMBLER_IS_MASM
#undef V8_ASSEMBLER_IS_MARMASM
......
......@@ -46,6 +46,9 @@ class PlatformEmbeddedFileWriterWin : public PlatformEmbeddedFileWriterBase {
int IndentedDataDirective(DataDirective directive) override;
DataDirective ByteChunkDataDirective() const override;
int WriteByteChunk(const uint8_t* data) override;
void StartPdataSection();
void EndPdataSection();
void StartXdataSection();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment