| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 91d41e7 commit b030004
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -877,9 +877,6 @@ | |||
| 877 | 877 | 'node_target_type=="executable"', { | |
| 878 | 878 | 'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ], | |
| 879 | 879 | }], | |
| 880 | - ['OS in "linux mac"', { | ||
| 881 | - 'defines': [ 'NODE_MKSNAPSHOT_USE_STRING_LITERALS' ], | ||
| 882 | - }], | ||
| 883 | 880 | [ 'use_openssl_def==1', { | |
| 884 | 881 | # TODO(bnoordhuis) Make all platforms export the same list of symbols. | |
| 885 | 882 | # Teach mkssldef.py to generate linker maps that UNIX linkers understand. | |
@@ -1248,6 +1245,9 @@ | |||
| 1248 | 1245 | ], | |
| 1249 | 1246 | ||
| 1250 | 1247 | 'conditions': [ | |
| 1248 | + ['OS in "linux mac"', { | ||
| 1249 | + 'defines': [ 'NODE_MKSNAPSHOT_USE_STRING_LITERALS=1' ], | ||
| 1250 | + }], | ||
| 1251 | 1251 | [ 'node_use_openssl=="true"', { | |
| 1252 | 1252 | 'defines': [ | |
| 1253 | 1253 | 'HAVE_OPENSSL=1', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,10 +18,12 @@ struct SnapshotData; | |||
| 18 | 18 | ||
| 19 | 19 | class NODE_EXTERN_PRIVATE SnapshotBuilder { | |
| 20 | 20 | public: | |
| 21 | - static ExitCode Generate(std::ostream& out, | ||
| 22 | - const std::vector<std::string>& args, | ||
| 23 | - const std::vector<std::string>& exec_args, | ||
| 24 | - std::optional<std::string_view> main_script); | ||
| 21 | + static ExitCode GenerateAsSource( | ||
| 22 | + const char* out_path, | ||
| 23 | + const std::vector<std::string>& args, | ||
| 24 | + const std::vector<std::string>& exec_args, | ||
| 25 | + std::optional<std::string_view> main_script_path = std::nullopt, | ||
| 26 | + bool use_string_literals = true); | ||
| 25 | 27 | ||
| 26 | 28 | // Generate the snapshot into out. | |
| 27 | 29 | static ExitCode Generate(SnapshotData* out, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | ||
| 2 | 2 | #include "node_snapshotable.h" | |
| 3 | + #include <fstream> | ||
| 3 | 4 | #include <iostream> | |
| 4 | 5 | #include <sstream> | |
| 5 | 6 | #include <vector> | |
@@ -715,13 +716,6 @@ SnapshotData::~SnapshotData() { | |||
| 715 | 716 | } | |
| 716 | 717 | } | |
| 717 | 718 | ||
| 718 | - template <typename T> | ||
| 719 | - void WriteVector(std::ostream* ss, const T* vec, size_t size) { | ||
| 720 | - for (size_t i = 0; i < size; i++) { | ||
| 721 | - *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ','); | ||
| 722 | - } | ||
| 723 | - } | ||
| 724 | - | ||
| 725 | 719 | static std::string GetCodeCacheDefName(const std::string& id) { | |
| 726 | 720 | char buf[64] = {0}; | |
| 727 | 721 | size_t size = id.size(); | |
@@ -746,48 +740,71 @@ static std::string FormatSize(size_t size) { | |||
| 746 | 740 | return buf; | |
| 747 | 741 | } | |
| 748 | 742 | ||
| 749 | - #ifdef NODE_MKSNAPSHOT_USE_STRING_LITERALS | ||
| 750 | - static void WriteDataAsCharString(std::ostream* ss, | ||
| 751 | - const uint8_t* data, | ||
| 752 | - size_t length) { | ||
| 753 | - for (size_t i = 0; i < length; i++) { | ||
| 754 | - const uint8_t ch = data[i]; | ||
| 755 | - // We can print most printable characters directly. The exceptions are '\' | ||
| 756 | - // (escape characters), " (would end the string), and ? (trigraphs). The | ||
| 757 | - // latter may be overly conservative: we compile with C++17 which doesn't | ||
| 758 | - // support trigraphs. | ||
| 759 | - if (ch >= ' ' && ch <= '~' && ch != '\\' && ch != '"' && ch != '?') { | ||
| 760 | - *ss << ch; | ||
| 761 | - } else { | ||
| 762 | - // All other characters are blindly output as octal. | ||
| 763 | - const char c0 = '0' + ((ch >> 6) & 7); | ||
| 764 | - const char c1 = '0' + ((ch >> 3) & 7); | ||
| 765 | - const char c2 = '0' + (ch & 7); | ||
| 766 | - *ss << "\\" << c0 << c1 << c2; | ||
| 767 | - } | ||
| 768 | - if (i % 64 == 63) { | ||
| 769 | - // Go to a newline every 64 bytes since many text editors have | ||
| 770 | - // problems with very long lines. | ||
| 771 | - *ss << "\"\n\""; | ||
| 772 | - } | ||
| 743 | + std::string ToOctalString(const uint8_t ch) { | ||
| 744 | + // We can print most printable characters directly. The exceptions are '\' | ||
| 745 | + // (escape characters), " (would end the string), and ? (trigraphs). The | ||
| 746 | + // latter may be overly conservative: we compile with C++17 which doesn't | ||
| 747 | + // support trigraphs. | ||
| 748 | + if (ch >= ' ' && ch <= '~' && ch != '\\' && ch != '"' && ch != '?') { | ||
| 749 | + return std::string(1, static_cast<char>(ch)); | ||
| 773 | 750 | } | |
| 751 | + // All other characters are blindly output as octal. | ||
| 752 | + const char c0 = '0' + ((ch >> 6) & 7); | ||
| 753 | + const char c1 = '0' + ((ch >> 3) & 7); | ||
| 754 | + const char c2 = '0' + (ch & 7); | ||
| 755 | + return std::string("\\") + c0 + c1 + c2; | ||
| 774 | 756 | } | |
| 775 | 757 | ||
| 776 | - static void WriteStaticCodeCacheDataAsStringLiteral( | ||
| 777 | - std::ostream* ss, const builtins::CodeCacheInfo& info) { | ||
| 778 | - *ss << "static const uint8_t *" << GetCodeCacheDefName(info.id) | ||
| 779 | - << "= reinterpret_cast<const uint8_t *>(\""; | ||
| 780 | - WriteDataAsCharString(ss, info.data.data, info.data.length); | ||
| 781 | - *ss << "\");\n"; | ||
| 758 | + std::vector<std::string> GetOctalTable() { | ||
| 759 | + size_t size = 1 << 8; | ||
| 760 | + std::vector<std::string> code_table(size); | ||
| 761 | + for (size_t i = 0; i < size; ++i) { | ||
| 762 | + code_table[i] = ToOctalString(static_cast<uint8_t>(i)); | ||
| 763 | + } | ||
| 764 | + return code_table; | ||
| 782 | 765 | } | |
| 783 | - #else | ||
| 784 | - static void WriteStaticCodeCacheDataAsArray( | ||
| 785 | - std::ostream* ss, const builtins::CodeCacheInfo& info) { | ||
| 786 | - *ss << "static const uint8_t " << GetCodeCacheDefName(info.id) << "[] = {\n"; | ||
| 787 | - WriteVector(ss, info.data.data, info.data.length); | ||
| 788 | - *ss << "};\n"; | ||
| 766 | + | ||
| 767 | + const std::string& GetOctalCode(uint8_t index) { | ||
| 768 | + static std::vector<std::string> table = GetOctalTable(); | ||
| 769 | + return table[index]; | ||
| 770 | + } | ||
| 771 | + | ||
| 772 | + template <typename T> | ||
| 773 | + void WriteByteVectorLiteral(std::ostream* ss, | ||
| 774 | + const T* vec, | ||
| 775 | + size_t size, | ||
| 776 | + const char* var_name, | ||
| 777 | + bool use_string_literals) { | ||
| 778 | + constexpr bool is_uint8_t = std::is_same_v<T, uint8_t>; | ||
| 779 | + static_assert(is_uint8_t || std::is_same_v<T, char>); | ||
| 780 | + constexpr const char* type_name = is_uint8_t ? "uint8_t" : "char"; | ||
| 781 | + if (use_string_literals) { | ||
| 782 | + const uint8_t* data = reinterpret_cast<const uint8_t*>(vec); | ||
| 783 | + *ss << "static const " << type_name << " *" << var_name << " = "; | ||
| 784 | + *ss << (is_uint8_t ? R"(reinterpret_cast<const uint8_t *>(")" : "\""); | ||
| 785 | + for (size_t i = 0; i < size; i++) { | ||
| 786 | + const uint8_t ch = data[i]; | ||
| 787 | + *ss << GetOctalCode(ch); | ||
| 788 | + if (i % 64 == 63) { | ||
| 789 | + // Go to a newline every 64 bytes since many text editors have | ||
| 790 | + // problems with very long lines. | ||
| 791 | + *ss << "\"\n\""; | ||
| 792 | + } | ||
| 793 | + } | ||
| 794 | + *ss << (is_uint8_t ? "\");\n" : "\";\n"); | ||
| 795 | + } else { | ||
| 796 | + *ss << "static const " << type_name << " " << var_name << "[] = {"; | ||
| 797 | + for (size_t i = 0; i < size; i++) { | ||
| 798 | + *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ','); | ||
| 799 | + if (i % 64 == 63) { | ||
| 800 | + // Print a newline every 64 units and a offset to improve | ||
| 801 | + // readability. | ||
| 802 | + *ss << " // " << (i / 64) << "\n"; | ||
| 803 | + } | ||
| 804 | + } | ||
| 805 | + *ss << "};\n"; | ||
| 806 | + } | ||
| 789 | 807 | } | |
| 790 | - #endif | ||
| 791 | 808 | ||
| 792 | 809 | static void WriteCodeCacheInitializer(std::ostream* ss, | |
| 793 | 810 | const std::string& id, | |
@@ -800,7 +817,9 @@ static void WriteCodeCacheInitializer(std::ostream* ss, | |||
| 800 | 817 | *ss << " },\n"; | |
| 801 | 818 | } | |
| 802 | 819 | ||
| 803 | - void FormatBlob(std::ostream& ss, const SnapshotData* data) { | ||
| 820 | + void FormatBlob(std::ostream& ss, | ||
| 821 | + const SnapshotData* data, | ||
| 822 | + bool use_string_literals) { | ||
| 804 | 823 | ss << R"(#include <cstddef> | |
| 805 | 824 | #include "env.h" | |
| 806 | 825 | #include "node_snapshot_builder.h" | |
@@ -811,32 +830,24 @@ void FormatBlob(std::ostream& ss, const SnapshotData* data) { | |||
| 811 | 830 | namespace node { | |
| 812 | 831 | )"; | |
| 813 | 832 | ||
| 814 | - #ifdef NODE_MKSNAPSHOT_USE_STRING_LITERALS | ||
| 815 | - ss << R"(static const char *v8_snapshot_blob_data = ")"; | ||
| 816 | - WriteDataAsCharString( | ||
| 817 | - &ss, | ||
| 818 | - reinterpret_cast<const uint8_t*>(data->v8_snapshot_blob_data.data), | ||
| 819 | - data->v8_snapshot_blob_data.raw_size); | ||
| 820 | - ss << R"(";)"; | ||
| 821 | - #else | ||
| 822 | - ss << R"(static const char v8_snapshot_blob_data[] = {)"; | ||
| 823 | - WriteVector(&ss, | ||
| 824 | - data->v8_snapshot_blob_data.data, | ||
| 825 | - data->v8_snapshot_blob_data.raw_size); | ||
| 826 | - ss << R"(};)"; | ||
| 827 | - #endif | ||
| 833 | + WriteByteVectorLiteral(&ss, | ||
| 834 | + data->v8_snapshot_blob_data.data, | ||
| 835 | + data->v8_snapshot_blob_data.raw_size, | ||
| 836 | + "v8_snapshot_blob_data", | ||
| 837 | + use_string_literals); | ||
| 828 | 838 | ||
| 829 | 839 | ss << R"(static const int v8_snapshot_blob_size = )" | |
| 830 | - << data->v8_snapshot_blob_data.raw_size << ";"; | ||
| 840 | + << data->v8_snapshot_blob_data.raw_size << ";\n"; | ||
| 831 | 841 | ||
| 842 | + // Windows can't deal with too many large vector initializers. | ||
| 843 | + // Store the data into static arrays first. | ||
| 832 | 844 | for (const auto& item : data->code_cache) { | |
| 833 | - #ifdef NODE_MKSNAPSHOT_USE_STRING_LITERALS | ||
| 834 | - WriteStaticCodeCacheDataAsStringLiteral(&ss, item); | ||
| 835 | - #else | ||
| 836 | - // Windows can't deal with too many large vector initializers. | ||
| 837 | - // Store the data into static arrays first. | ||
| 838 | - WriteStaticCodeCacheDataAsArray(&ss, item); | ||
| 839 | - #endif | ||
| 845 | + std::string var_name = GetCodeCacheDefName(item.id); | ||
| 846 | + WriteByteVectorLiteral(&ss, | ||
| 847 | + item.data.data, | ||
| 848 | + item.data.length, | ||
| 849 | + var_name.c_str(), | ||
| 850 | + use_string_literals); | ||
| 840 | 851 | } | |
| 841 | 852 | ||
| 842 | 853 | ss << R"(const SnapshotData snapshot_data { | |
@@ -1073,17 +1084,45 @@ ExitCode SnapshotBuilder::CreateSnapshot(SnapshotData* out, | |||
| 1073 | 1084 | return ExitCode::kNoFailure; | |
| 1074 | 1085 | } | |
| 1075 | 1086 | ||
| 1076 | - ExitCode SnapshotBuilder::Generate( | ||
| 1077 | - std::ostream& out, | ||
| 1087 | + ExitCode SnapshotBuilder::GenerateAsSource( | ||
| 1088 | + const char* out_path, | ||
| 1078 | 1089 | const std::vector<std::string>& args, | |
| 1079 | 1090 | const std::vector<std::string>& exec_args, | |
| 1080 | - std::optional<std::string_view> main_script) { | ||
| 1091 | + std::optional<std::string_view> main_script_path, | ||
| 1092 | + bool use_string_literals) { | ||
| 1093 | + std::string main_script_content; | ||
| 1094 | + std::optional<std::string_view> main_script_optional; | ||
| 1095 | + if (main_script_path.has_value()) { | ||
| 1096 | + int r = ReadFileSync(&main_script_content, main_script_path.value().data()); | ||
| 1097 | + if (r != 0) { | ||
| 1098 | + FPrintF(stderr, | ||
| 1099 | + "Cannot read main script %s for building snapshot. %s: %s", | ||
| 1100 | + main_script_path.value(), | ||
| 1101 | + uv_err_name(r), | ||
| 1102 | + uv_strerror(r)); | ||
| 1103 | + return ExitCode::kGenericUserError; | ||
| 1104 | + } | ||
| 1105 | + main_script_optional = main_script_content; | ||
| 1106 | + } | ||
| 1107 | + | ||
| 1108 | + std::ofstream out(out_path, std::ios::out | std::ios::binary); | ||
| 1109 | + if (!out) { | ||
| 1110 | + FPrintF(stderr, "Cannot open %s for output.\n", out_path); | ||
| 1111 | + return ExitCode::kGenericUserError; | ||
| 1112 | + } | ||
| 1113 | + | ||
| 1081 | 1114 | SnapshotData data; | |
| 1082 | - ExitCode exit_code = Generate(&data, args, exec_args, main_script); | ||
| 1115 | + ExitCode exit_code = Generate(&data, args, exec_args, main_script_optional); | ||
| 1083 | 1116 | if (exit_code != ExitCode::kNoFailure) { | |
| 1084 | 1117 | return exit_code; | |
| 1085 | 1118 | } | |
| 1086 | - FormatBlob(out, &data); | ||
| 1119 | + FormatBlob(out, &data, use_string_literals); | ||
| 1120 | + | ||
| 1121 | + if (!out) { | ||
| 1122 | + std::cerr << "Failed to write to " << out_path << "\n"; | ||
| 1123 | + exit_code = node::ExitCode::kGenericUserError; | ||
| 1124 | + } | ||
| 1125 | + | ||
| 1087 | 1126 | return exit_code; | |
| 1088 | 1127 | } | |
| 1089 | 1128 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,4 @@ | |||
| 1 | 1 | #include <cstdio> | |
| 2 | - #include <fstream> | ||
| 3 | 2 | #include <iostream> | |
| 4 | 3 | #include <sstream> | |
| 5 | 4 | #include <string> | |
@@ -72,29 +71,26 @@ int BuildSnapshot(int argc, char* argv[]) { | |||
| 72 | 71 | CHECK_EQ(result->exit_code(), 0); | |
| 73 | 72 | ||
| 74 | 73 | std::string out_path; | |
| 74 | + std::optional<std::string_view> main_script_path = std::nullopt; | ||
| 75 | 75 | if (node::per_process::cli_options->per_isolate->build_snapshot) { | |
| 76 | + main_script_path = result->args()[1]; | ||
| 76 | 77 | out_path = result->args()[2]; | |
| 77 | 78 | } else { | |
| 78 | 79 | out_path = result->args()[1]; | |
| 79 | 80 | } | |
| 80 | 81 | ||
| 81 | - std::ofstream out(out_path, std::ios::out | std::ios::binary); | ||
| 82 | - if (!out) { | ||
| 83 | - std::cerr << "Cannot open " << out_path << "\n"; | ||
| 84 | - return 1; | ||
| 85 | - } | ||
| 82 | + #ifdef NODE_MKSNAPSHOT_USE_STRING_LITERALS | ||
| 83 | + bool use_string_literals = true; | ||
| 84 | + #else | ||
| 85 | + bool use_string_literals = false; | ||
| 86 | + #endif | ||
| 86 | 87 | ||
| 87 | - node::ExitCode exit_code = node::ExitCode::kNoFailure; | ||
| 88 | - { | ||
| 89 | - exit_code = node::SnapshotBuilder::Generate( | ||
| 90 | - out, result->args(), result->exec_args(), std::nullopt); | ||
| 91 | - if (exit_code == node::ExitCode::kNoFailure) { | ||
| 92 | - if (!out) { | ||
| 93 | - std::cerr << "Failed to write " << out_path << "\n"; | ||
| 94 | - exit_code = node::ExitCode::kGenericUserError; | ||
| 95 | - } | ||
| 96 | - } | ||
| 97 | - } | ||
| 88 | + node::ExitCode exit_code = | ||
| 89 | + node::SnapshotBuilder::GenerateAsSource(out_path.c_str(), | ||
| 90 | + result->args(), | ||
| 91 | + result->exec_args(), | ||
| 92 | + main_script_path, | ||
| 93 | + use_string_literals); | ||
| 98 | 94 | ||
| 99 | 95 | node::TearDownOncePerProcess(); | |
| 100 | 96 | return static_cast<int>(exit_code); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments