Commit 4ca93a64 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[builtins] Reduce the generated embedded.S file size on windows

Windows MASM becomes extremely slow when given very large data streams.
Runtime behavior is super-linear, with compile times of

  5s for 50 KLOC in embedded.S
 15s for 100KLOC
 40s for 150KLOC

Compilation of the 320KLOC file produced for debug builds took more than
5 minutes.

This CL reduces compile time by emitting QWORD directives instead,
which reduces the emitted debug embedded.S to around 120KLOC and
compile times to around 40s.

Bug: v8:8475,v8:6666
Change-Id: I19903cdf7d1b70a65c00ca67f40129847b17f386
Reviewed-on: https://chromium-review.googlesource.com/c/1341951Reviewed-by: 's avatarDan Elphick <delphick@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57609}
parent f1f5c110
......@@ -4,6 +4,8 @@
#include "src/snapshot/embedded-file-writer.h"
#include <cinttypes>
namespace v8 {
namespace internal {
......@@ -117,8 +119,8 @@ void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
}
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
return fprintf(fp_, "0x%x", value);
int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
return fprintf(fp_, "0x%" PRIx64, value);
}
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
......@@ -194,8 +196,8 @@ void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
}
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
return fprintf(fp_, "0x%x", value);
int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
return fprintf(fp_, "0x%" PRIx64, value);
}
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
......@@ -292,8 +294,8 @@ void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
#endif
}
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
return fprintf(fp_, "0%xh", value);
int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
return fprintf(fp_, "0%" PRIx64 "h", value);
}
void PlatformDependentEmbeddedFileWriter::FilePrologue() {
......@@ -383,8 +385,8 @@ void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
}
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
return fprintf(fp_, "0x%x", value);
int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) {
return fprintf(fp_, "0x%" PRIx64, value);
}
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
......
......@@ -44,7 +44,7 @@ class PlatformDependentEmbeddedFileWriter final {
void DeclareFunctionEnd(const char* name);
// Returns the number of printed characters.
int HexLiteral(int value);
int HexLiteral(uint64_t value);
void Comment(const char* string);
void Newline() { fprintf(fp_, "\n"); }
......@@ -203,7 +203,29 @@ class EmbeddedFileWriter {
w->FileEpilogue();
}
static int WriteOcta(FILE* fp, int current_line_length, const uint8_t* data) {
#ifdef V8_OS_WIN
// 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.
// TODO(v8:8475): Use nasm or yasm instead of MASM.
static constexpr DataDirective kByteChunkDirective = kQuad;
static constexpr int kByteChunkSize = 8;
static int WriteByteChunk(PlatformDependentEmbeddedFileWriter* 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);
}
#else // V8_OS_WIN
static constexpr DataDirective kByteChunkDirective = kOcta;
static constexpr int kByteChunkSize = 16;
static int WriteByteChunk(PlatformDependentEmbeddedFileWriter* w,
int current_line_length, const uint8_t* data) {
const uint64_t* quad_ptr1 = reinterpret_cast<const uint64_t*>(data);
const uint64_t* quad_ptr2 = reinterpret_cast<const uint64_t*>(data + 8);
......@@ -217,12 +239,13 @@ class EmbeddedFileWriter {
if (part1 != 0) {
current_line_length +=
fprintf(fp, "0x%" PRIx64 "%016" PRIx64, part1, part2);
fprintf(w->fp(), "0x%" PRIx64 "%016" PRIx64, part1, part2);
} else {
current_line_length += fprintf(fp, "0x%" PRIx64, part2);
current_line_length += fprintf(w->fp(), "0x%" PRIx64, part2);
}
return current_line_length;
}
#endif // V8_OS_WIN
static int WriteDirectiveOrSeparator(PlatformDependentEmbeddedFileWriter* w,
int current_line_length,
......@@ -238,14 +261,14 @@ class EmbeddedFileWriter {
return current_line_length + printed_chars;
}
static int WriteLineEndIfNeeded(FILE* fp, int current_line_length,
int write_size) {
static const int kTextWidth = 80;
static int WriteLineEndIfNeeded(PlatformDependentEmbeddedFileWriter* w,
int current_line_length, int write_size) {
static const int kTextWidth = 100;
// Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use
// the actual size of the string to be written to determine this so it's
// more conservative than strictly needed.
if (current_line_length + strlen(",0x") + write_size * 2 > kTextWidth) {
fprintf(fp, "\n");
fprintf(w->fp(), "\n");
return 0;
} else {
return current_line_length;
......@@ -258,24 +281,24 @@ class EmbeddedFileWriter {
int current_line_length = 0;
uint32_t i = 0;
#ifndef V8_OS_WIN
const uint32_t size_of_octa = 16;
for (; i <= size - size_of_octa; i += size_of_octa) {
current_line_length =
WriteDirectiveOrSeparator(w, current_line_length, kOcta);
current_line_length = WriteOcta(w->fp(), current_line_length, data + i);
// Begin by writing out byte chunks.
for (; i <= size - kByteChunkSize; i += kByteChunkSize) {
current_line_length = WriteDirectiveOrSeparator(w, current_line_length,
kByteChunkDirective);
current_line_length = WriteByteChunk(w, current_line_length, data + i);
current_line_length =
WriteLineEndIfNeeded(w->fp(), current_line_length, size_of_octa);
WriteLineEndIfNeeded(w, current_line_length, kByteChunkSize);
}
if (current_line_length != 0) w->Newline();
current_line_length = 0;
#endif
// Write any trailing bytes one-by-one.
for (; i < size; i++) {
current_line_length =
WriteDirectiveOrSeparator(w, current_line_length, kByte);
current_line_length += w->HexLiteral(data[i]);
current_line_length =
WriteLineEndIfNeeded(w->fp(), current_line_length, 1);
current_line_length = WriteLineEndIfNeeded(w, current_line_length, 1);
}
if (current_line_length != 0) w->Newline();
}
......
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