build: add --write-snapshot-as-array-literals to configure.py

This makes it easier to locate indeterminism in the snapshot, with
the following command:

$ ./configure --write-snapshot-as-array-literals
$ make V=
$ mv out/Release/obj/gen/node_snapshot.cc ./node_snapshot.cc
$ make V=
$ diff out/Release/obj/gen/node_snapshot.cc ./node_snapshot.cc

PR-URL: https://github.com/nodejs/node/pull/49312
Refs: https://github.com/nodejs/build/issues/3043
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Joyee Cheung 2023-08-24 18:02:26 +02:00
parent 4d0f930183
commit 0028fd12b7
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
5 changed files with 28 additions and 14 deletions

View File

@ -609,6 +609,14 @@ parser.add_argument('--with-ltcg',
default=None,
help='Use Link Time Code Generation. This feature is only available on Windows.')
parser.add_argument('--write-snapshot-as-array-literals',
action='store_true',
dest='write_snapshot_as_array_literals',
default=None,
help='Write the snapshot data as array literals for readability.'
'By default the snapshot data may be written as string literals on some '
'platforms to speed up compilation.')
parser.add_argument('--without-node-snapshot',
action='store_true',
dest='without_node_snapshot',
@ -1290,6 +1298,11 @@ def configure_node(o):
o['variables']['node_use_node_code_cache'] = b(
not cross_compiling and not options.shared)
if options.write_snapshot_as_array_literals is not None:
o['variables']['node_write_snapshot_as_array_literals'] = b(options.write_snapshot_as_array_literals)
else:
o['variables']['node_write_snapshot_as_array_literals'] = b(flavor != 'mac' and flavor != 'linux')
if target_arch == 'arm':
configure_arm(o)
elif target_arch in ('mips', 'mipsel', 'mips64el'):

View File

@ -10,6 +10,7 @@
'node_use_v8_platform%': 'true',
'node_use_bundled_v8%': 'true',
'node_shared%': 'false',
'node_write_snapshot_as_string_literals': 'true',
'force_dynamic_crt%': 0,
'ossfuzz' : 'false',
'node_module_version%': '',
@ -1255,8 +1256,8 @@
],
'conditions': [
['OS in "linux mac"', {
'defines': [ 'NODE_MKSNAPSHOT_USE_STRING_LITERALS=1' ],
['node_write_snapshot_as_array_literals=="true"', {
'defines': [ 'NODE_MKSNAPSHOT_USE_ARRAY_LITERALS=1' ],
}],
[ 'node_use_openssl=="true"', {
'defines': [

View File

@ -23,7 +23,7 @@ class NODE_EXTERN_PRIVATE SnapshotBuilder {
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args,
std::optional<std::string_view> main_script_path = std::nullopt,
bool use_string_literals = true);
bool use_array_literals = false);
// Generate the snapshot into out.
static ExitCode Generate(SnapshotData* out,

View File

@ -773,11 +773,11 @@ void WriteByteVectorLiteral(std::ostream* ss,
const T* vec,
size_t size,
const char* var_name,
bool use_string_literals) {
bool use_array_literals) {
constexpr bool is_uint8_t = std::is_same_v<T, uint8_t>;
static_assert(is_uint8_t || std::is_same_v<T, char>);
constexpr const char* type_name = is_uint8_t ? "uint8_t" : "char";
if (use_string_literals) {
if (!use_array_literals) {
const uint8_t* data = reinterpret_cast<const uint8_t*>(vec);
*ss << "static const " << type_name << " *" << var_name << " = ";
*ss << (is_uint8_t ? R"(reinterpret_cast<const uint8_t *>(")" : "\"");
@ -818,7 +818,7 @@ static void WriteCodeCacheInitializer(std::ostream* ss,
void FormatBlob(std::ostream& ss,
const SnapshotData* data,
bool use_string_literals) {
bool use_array_literals) {
ss << R"(#include <cstddef>
#include "env.h"
#include "node_snapshot_builder.h"
@ -833,7 +833,7 @@ namespace node {
data->v8_snapshot_blob_data.data,
data->v8_snapshot_blob_data.raw_size,
"v8_snapshot_blob_data",
use_string_literals);
use_array_literals);
ss << R"(static const int v8_snapshot_blob_size = )"
<< data->v8_snapshot_blob_data.raw_size << ";\n";
@ -846,7 +846,7 @@ namespace node {
item.data.data,
item.data.length,
var_name.c_str(),
use_string_literals);
use_array_literals);
}
ss << R"(const SnapshotData snapshot_data {
@ -1132,7 +1132,7 @@ ExitCode SnapshotBuilder::GenerateAsSource(
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args,
std::optional<std::string_view> main_script_path,
bool use_string_literals) {
bool use_array_literals) {
std::string main_script_content;
std::optional<std::string_view> main_script_optional;
if (main_script_path.has_value()) {
@ -1159,7 +1159,7 @@ ExitCode SnapshotBuilder::GenerateAsSource(
if (exit_code != ExitCode::kNoFailure) {
return exit_code;
}
FormatBlob(out, &data, use_string_literals);
FormatBlob(out, &data, use_array_literals);
if (!out) {
std::cerr << "Failed to write to " << out_path << "\n";

View File

@ -79,10 +79,10 @@ int BuildSnapshot(int argc, char* argv[]) {
out_path = result->args()[1];
}
#ifdef NODE_MKSNAPSHOT_USE_STRING_LITERALS
bool use_string_literals = true;
#ifdef NODE_MKSNAPSHOT_USE_ARRAY_LITERALS
bool use_array_literals = true;
#else
bool use_string_literals = false;
bool use_array_literals = false;
#endif
node::ExitCode exit_code =
@ -90,7 +90,7 @@ int BuildSnapshot(int argc, char* argv[]) {
result->args(),
result->exec_args(),
main_script_path,
use_string_literals);
use_array_literals);
node::TearDownOncePerProcess();
return static_cast<int>(exit_code);