From 0e5a828f629bd4c3541301854c6c06670da47a6b Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Sun, 5 Jan 2020 19:48:46 -0800 Subject: [PATCH 1/2] build: add support for section ordering Adds support for using a section ordering file with the gold linker. This makes it possible to reorder functions in a build to optimize for a specific workload. `hfsort` is a tool that can be used to generate such a file from perf- recorded last branch record (LBR) data by running Node.js as `node --perf-basic-prof`. Refs: https://github.com/facebook/hhvm/tree/9966d482c19c6120c621c6f3896525fb19fb3842/hphp/tools/hfsort Refs: https://software.intel.com/content/www/us/en/develop/articles/runtime-optimization-blueprint-IA-optimization-with-last-branch-record.html Refs: https://github.com/nodejs/node/pull/16891/ Signed-off-by: Gabriel Schulhof --- common.gypi | 10 ++++++++++ configure.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/common.gypi b/common.gypi index 46b4633f5d7e85..32cf1304e706be 100644 --- a/common.gypi +++ b/common.gypi @@ -172,6 +172,16 @@ }, 'cflags': [ '-O3' ], 'conditions': [ + ['node_section_ordering_file!="-"', { + 'cflags': [ + '-fuse-ld=gold', + '-ffunction-sections', + ], + 'ldflags': [ + '-fuse-ld=gold', + '-Wl,--section-ordering-file=<(node_section_ordering_file)', + ] + }], ['OS=="solaris"', { # pull in V8's postmortem metadata 'ldflags': [ '-Wl,-z,allextract' ] diff --git a/configure.py b/configure.py index 5134892cb5234a..2f69519b6a1f3c 100755 --- a/configure.py +++ b/configure.py @@ -502,6 +502,14 @@ dest='node_use_large_pages_script_lld', help='This option has no effect. --use-largepages is now a runtime option.') +parser.add_option('--use-section-ordering-file', + action='store', + dest='node_section_ordering_file', + default='', + help='Pass a section ordering file to the linker. This requires that ' + + 'Node.js be linked using the gold linker. The gold linker must have ' + + 'version 1.2 or greater.') + intl_optgroup.add_option('--with-intl', action='store', dest='with_intl', @@ -1766,6 +1774,29 @@ def configure_inspector(o): options.without_ssl) o['variables']['v8_enable_inspector'] = 0 if disable_inspector else 1 +def configure_section_file(o): + try: + proc = subprocess.Popen(['ld.gold'] + ['-v'], stdin = subprocess.PIPE, + stdout = subprocess.PIPE, stderr = subprocess.PIPE) + except OSError: + return 0 + + match = re.match(r"^GNU gold.*([0-9]+)\.([0-9]+)$", + proc.communicate()[0].decode("utf-8")) + + if match: + gold_major_version = match.group(1) + gold_minor_version = match.group(2) + if int(gold_major_version) == 1 and int(gold_minor_version) <= 1: + error('''GNU gold version must be greater than 1.2 in order to use section + reordering''') + + if options.node_section_ordering_file != "": + o['variables']['node_section_ordering_file'] = os.path.realpath( + str(options.node_section_ordering_file)) + else: + # An empty string here will cause gyp to fail. + o['variables']['node_section_ordering_file'] = "-" def make_bin_override(): if sys.platform == 'win32': @@ -1831,6 +1862,7 @@ def make_bin_override(): configure_intl(output) configure_static(output) configure_inspector(output) +configure_section_file(output) # Forward OSS-Fuzz settings output['variables']['ossfuzz'] = b(options.ossfuzz) From dff2255987f3bb4d24d0a3701f882862ef6893ef Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Mon, 28 Sep 2020 19:32:42 -0700 Subject: [PATCH 2/2] address review comments --- common.gypi | 23 +++++++++++++++-------- configure.py | 12 ++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/common.gypi b/common.gypi index 32cf1304e706be..33b1325eb513ea 100644 --- a/common.gypi +++ b/common.gypi @@ -111,6 +111,9 @@ ['target_arch in "ppc64 s390x"', { 'v8_enable_backtrace': 1, }], + ['OS=="linux"', { + 'node_section_ordering_info%': '' + }] ], }, @@ -172,15 +175,19 @@ }, 'cflags': [ '-O3' ], 'conditions': [ - ['node_section_ordering_file!="-"', { - 'cflags': [ - '-fuse-ld=gold', - '-ffunction-sections', + ['OS=="linux"', { + 'conditions': [ + ['node_section_ordering_info!=""', { + 'cflags': [ + '-fuse-ld=gold', + '-ffunction-sections', + ], + 'ldflags': [ + '-fuse-ld=gold', + '-Wl,--section-ordering-file=<(node_section_ordering_info)', + ], + }], ], - 'ldflags': [ - '-fuse-ld=gold', - '-Wl,--section-ordering-file=<(node_section_ordering_file)', - ] }], ['OS=="solaris"', { # pull in V8's postmortem metadata diff --git a/configure.py b/configure.py index 2f69519b6a1f3c..4b42c1b35a6b99 100755 --- a/configure.py +++ b/configure.py @@ -504,7 +504,7 @@ parser.add_option('--use-section-ordering-file', action='store', - dest='node_section_ordering_file', + dest='node_section_ordering_info', default='', help='Pass a section ordering file to the linker. This requires that ' + 'Node.js be linked using the gold linker. The gold linker must have ' + @@ -1779,6 +1779,7 @@ def configure_section_file(o): proc = subprocess.Popen(['ld.gold'] + ['-v'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) except OSError: + warn('''No acceptable ld.gold linker found!''') return 0 match = re.match(r"^GNU gold.*([0-9]+)\.([0-9]+)$", @@ -1791,12 +1792,11 @@ def configure_section_file(o): error('''GNU gold version must be greater than 1.2 in order to use section reordering''') - if options.node_section_ordering_file != "": - o['variables']['node_section_ordering_file'] = os.path.realpath( - str(options.node_section_ordering_file)) + if options.node_section_ordering_info != "": + o['variables']['node_section_ordering_info'] = os.path.realpath( + str(options.node_section_ordering_info)) else: - # An empty string here will cause gyp to fail. - o['variables']['node_section_ordering_file'] = "-" + o['variables']['node_section_ordering_info'] = "" def make_bin_override(): if sys.platform == 'win32':