summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2016-05-13 23:08:43 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2016-10-25 13:16:16 +0200
commite4290dec2df252cbaaf79098784730924153b182 (patch)
tree59af9bb9844049aea0c7322d6567e570c47dc213 /tools
parent2a456162b67e914eec77849623dcdb87011a482f (diff)
downloadandroid-node-v8-e4290dec2df252cbaaf79098784730924153b182.tar.gz
android-node-v8-e4290dec2df252cbaaf79098784730924153b182.tar.bz2
android-node-v8-e4290dec2df252cbaaf79098784730924153b182.zip
src,tools: speed up startup by 2.5%
Use zero-copy external string resources for storing the built-in JS source code. Saves a few hundred kilobyte of memory and consistently speeds up `benchmark/misc/startup.js` by 2.5%. Everything old is new again! Commit 74954ce ("Add string class that uses ExternalAsciiStringResource.") from 2011 did the same thing but I removed that in 2013 in commit 34b0a36 ("src: don't use NewExternal() with unaligned strings") because of a limitation in the V8 API. V8 no longer requires that strings are aligned if they are one-byte strings so it should be safe to re-enable external strings again. PR-URL: https://github.com/nodejs/node/pull/5458 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Robert Jefe Lindstaedt <robert.lindstaedt@gmail.com>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/js2c.py164
1 files changed, 31 insertions, 133 deletions
diff --git a/tools/js2c.py b/tools/js2c.py
index 40c30cc032..4808c56813 100755
--- a/tools/js2c.py
+++ b/tools/js2c.py
@@ -37,8 +37,11 @@ import sys
import string
-def ToCArray(filename, lines):
- return ','.join(str(ord(c)) for c in lines)
+def ToCString(contents):
+ step = 20
+ slices = (contents[i:i+step] for i in xrange(0, len(contents), step))
+ slices = map(lambda s: ','.join(str(ord(c)) for c in s), slices)
+ return ',\n'.join(slices)
def ReadFile(filename):
@@ -61,21 +64,6 @@ def ReadLines(filename):
return result
-def LoadConfigFrom(name):
- import ConfigParser
- config = ConfigParser.ConfigParser()
- config.read(name)
- return config
-
-
-def ParseValue(string):
- string = string.strip()
- if string.startswith('[') and string.endswith(']'):
- return string.lstrip('[').rstrip(']').split()
- else:
- return string
-
-
def ExpandConstants(lines, constants):
for key, value in constants.items():
lines = lines.replace(key, str(value))
@@ -174,53 +162,37 @@ def ReadMacros(lines):
HEADER_TEMPLATE = """\
-#ifndef node_natives_h
-#define node_natives_h
-namespace node {
-
-%(source_lines)s\
+#ifndef NODE_NATIVES_H_
+#define NODE_NATIVES_H_
-struct _native {
- const char* name;
- const unsigned char* source;
- size_t source_len;
-};
+#include <stdint.h>
-static const struct _native natives[] = { %(native_lines)s };
+#define NODE_NATIVES_MAP(V) \\
+{node_natives_map}
-}
-#endif
-"""
-
-
-NATIVE_DECLARATION = """\
- { "%(id)s", %(escaped_id)s_native, sizeof(%(escaped_id)s_native) },
-"""
+namespace node {{
+{sources}
+}} // namespace node
-SOURCE_DECLARATION = """\
- const unsigned char %(escaped_id)s_native[] = { %(data)s };
+#endif // NODE_NATIVES_H_
"""
-GET_DELAY_INDEX_CASE = """\
- if (strcmp(name, "%(id)s") == 0) return %(i)i;
+NODE_NATIVES_MAP = """\
+ V({escaped_id}) \\
"""
-GET_DELAY_SCRIPT_SOURCE_CASE = """\
- if (index == %(i)i) return Vector<const char>(%(id)s, %(length)i);
+SOURCES = """\
+static const uint8_t {escaped_id}_name[] = {{
+{name}}};
+static const uint8_t {escaped_id}_data[] = {{
+{data}}};
"""
-GET_DELAY_SCRIPT_NAME_CASE = """\
- if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i);
-"""
-
def JS2C(source, target):
- ids = []
- delay_ids = []
modules = []
- # Locate the macros file name.
consts = {}
macros = {}
macro_lines = []
@@ -235,18 +207,14 @@ def JS2C(source, target):
(consts, macros) = ReadMacros(macro_lines)
# Build source code lines
- source_lines = [ ]
- source_lines_empty = []
-
- native_lines = []
+ node_natives_map = []
+ sources = []
for s in modules:
- delay = str(s).endswith('-delay.js')
lines = ReadFile(str(s))
-
lines = ExpandConstants(lines, consts)
lines = ExpandMacros(lines, macros)
- data = ToCArray(s, lines)
+ data = ToCString(lines)
# On Windows, "./foo.bar" in the .gyp file is passed as "foo.bar"
# so don't assume there is always a slash in the file path.
@@ -258,89 +226,19 @@ def JS2C(source, target):
if '.' in id:
id = id.split('.', 1)[0]
- if delay: id = id[:-6]
- if delay:
- delay_ids.append((id, len(lines)))
- else:
- ids.append((id, len(lines)))
-
+ name = ToCString(id)
escaped_id = id.replace('-', '_').replace('/', '_')
- source_lines.append(SOURCE_DECLARATION % {
- 'id': id,
- 'escaped_id': escaped_id,
- 'data': data
- })
- source_lines_empty.append(SOURCE_DECLARATION % {
- 'id': id,
- 'escaped_id': escaped_id,
- 'data': 0
- })
- native_lines.append(NATIVE_DECLARATION % {
- 'id': id,
- 'escaped_id': escaped_id
- })
-
- # Build delay support functions
- get_index_cases = [ ]
- get_script_source_cases = [ ]
- get_script_name_cases = [ ]
-
- i = 0
- for (id, length) in delay_ids:
- native_name = "native %s.js" % id
- get_index_cases.append(GET_DELAY_INDEX_CASE % { 'id': id, 'i': i })
- get_script_source_cases.append(GET_DELAY_SCRIPT_SOURCE_CASE % {
- 'id': id,
- 'length': length,
- 'i': i
- })
- get_script_name_cases.append(GET_DELAY_SCRIPT_NAME_CASE % {
- 'name': native_name,
- 'length': len(native_name),
- 'i': i
- });
- i = i + 1
-
- for (id, length) in ids:
- native_name = "native %s.js" % id
- get_index_cases.append(GET_DELAY_INDEX_CASE % { 'id': id, 'i': i })
- get_script_source_cases.append(GET_DELAY_SCRIPT_SOURCE_CASE % {
- 'id': id,
- 'length': length,
- 'i': i
- })
- get_script_name_cases.append(GET_DELAY_SCRIPT_NAME_CASE % {
- 'name': native_name,
- 'length': len(native_name),
- 'i': i
- });
- i = i + 1
+ node_natives_map.append(NODE_NATIVES_MAP.format(**locals()))
+ sources.append(SOURCES.format(**locals()))
+
+ node_natives_map = ''.join(node_natives_map)
+ sources = ''.join(sources)
# Emit result
output = open(str(target[0]), "w")
- output.write(HEADER_TEMPLATE % {
- 'builtin_count': len(ids) + len(delay_ids),
- 'delay_count': len(delay_ids),
- 'source_lines': "\n".join(source_lines),
- 'native_lines': "\n".join(native_lines),
- 'get_index_cases': "".join(get_index_cases),
- 'get_script_source_cases': "".join(get_script_source_cases),
- 'get_script_name_cases': "".join(get_script_name_cases)
- })
+ output.write(HEADER_TEMPLATE.format(**locals()))
output.close()
- if len(target) > 1:
- output = open(str(target[1]), "w")
- output.write(HEADER_TEMPLATE % {
- 'builtin_count': len(ids) + len(delay_ids),
- 'delay_count': len(delay_ids),
- 'source_lines': "\n".join(source_lines_empty),
- 'get_index_cases': "".join(get_index_cases),
- 'get_script_source_cases': "".join(get_script_source_cases),
- 'get_script_name_cases': "".join(get_script_name_cases)
- })
- output.close()
-
def main():
natives = sys.argv[1]
source_files = sys.argv[2:]