From 52ef2ee57fd75640aebdb7578aefb5303547dcc7 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 18 Nov 2011 09:48:54 +0100 Subject: Add V8 snapshot support A V8 snapshot is a serialized representation of the JavaScript heap. Using a snapshot can vastly speed up V8 initialization. This commit introduces a new tool, mkv8snapshot. mkv8snapshot is automatically invoked as part of building QtV8, and generates a .cpp file which is compiled into the QtV8 library. Because mkv8snapshot itself needs to initialize the V8 environment the non-snapshot way (i.e., by evaluating thousands of lines of JavaScript), it needs to build all of V8. This means that V8 is effectively built twice when snapshots are enabled. When cross-compiling, only host=i386 and target=arm is supported, since that's the only relevant case for which V8 currently supports a simulator. mkv8snapshot is built and run as a host tool (using the simulator), and generates a snapshot that will be used on the target. Task-number: QTBUG-21152 Change-Id: I9270652f129505508f78db8b0a39fbf57dc8b86d Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- .gitignore | 1 + configure | 28 +++++++++++++++++++++++ src/tools/mkv8snapshot/mkv8snapshot.pro | 30 +++++++++++++++++++++++++ src/tools/tools.pro | 3 +++ src/v8/v8.pri | 40 ++++++++++++++------------------- src/v8/v8.pro | 16 +++++++++++++ tools/configure/configureapp.cpp | 10 ++++++++- 7 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 src/tools/mkv8snapshot/mkv8snapshot.pro diff --git a/.gitignore b/.gitignore index 6cc7f6d836..03883f652e 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ bin/linguist* bin/lrelease* bin/lupdate* bin/lconvert* +bin/mkv8snapshot* bin/moc* bin/makeqpf* bin/pixeltool* diff --git a/configure b/configure index 1d3e4d921d..f6b629ad84 100755 --- a/configure +++ b/configure @@ -705,6 +705,7 @@ CFG_MULTIMEDIA=auto CFG_AUDIO_BACKEND=auto CFG_SVG=auto CFG_V8=auto +CFG_V8SNAPSHOT=auto CFG_DECLARATIVE=auto CFG_DECLARATIVE_DEBUG=yes CFG_WEBKIT=auto # (yes|no|auto|debug) @@ -7270,6 +7271,7 @@ canBuildQtXmlPatterns="yes" canBuildWebKit="$HAVE_STL" canBuildQtConcurrent="yes" canBuildV8="yes" +canUseV8Snapshot="yes" # WebKit requires stdint.h "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stdint "Stdint" $L_FLAGS $I_FLAGS $l_FLAGS @@ -7502,6 +7504,25 @@ if [ "$CFG_V8" = "no" ]; then QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_V8" else QT_CONFIG="$QT_CONFIG v8" + # Detect snapshot support + if [ "$CFG_ARCH" != "$CFG_HOST_ARCH" ]; then + case "$CFG_HOST_ARCH,$CFG_ARCH" in + i386,arm) + ;; + *) canUseV8Snapshot="no" + ;; + esac + fi + if [ "$CFG_V8SNAPSHOT" = "auto" ]; then + CFG_V8SNAPSHOT="$canUseV8Snapshot" + fi + if [ "$CFG_V8SNAPSHOT" = "yes" -a "$canUseV8Snapshot" = "no" ]; then + echo "Error: V8 snapshot was requested, but is not supported on this platform." + exit 1 + fi + if [ "$CFG_V8SNAPSHOT" = "yes" ]; then + QT_CONFIG="$QT_CONFIG v8snapshot" + fi fi if [ "$CFG_DECLARATIVE" = "yes" ]; then @@ -8666,6 +8687,13 @@ for file in .projects .projects.3; do *examples/activeqt/*) continue ;; */qmake/qmake.pro) continue ;; *tools/bootstrap*|*tools/moc*|*tools/rcc*|*tools/uic*|*linguist/lrelease*) SPEC=$QMAKESPEC ;; + *tools/mkv8snapshot/*) + if [ "$CFG_V8" = "yes" -a "$CFG_V8SNAPSHOT" = "yes" ]; then + SPEC=$QMAKESPEC + else + continue + fi + ;; *) if [ "$CFG_NOPROCESS" = "yes" ]; then continue else diff --git a/src/tools/mkv8snapshot/mkv8snapshot.pro b/src/tools/mkv8snapshot/mkv8snapshot.pro new file mode 100644 index 0000000000..8e80ce2635 --- /dev/null +++ b/src/tools/mkv8snapshot/mkv8snapshot.pro @@ -0,0 +1,30 @@ +TEMPLATE = app +TARGET = mkv8snapshot +QT = +CONFIG -= app_bundle +CONFIG -= qt +CONFIG += console + +DESTDIR = ../../../bin +INCLUDEPATH += . +DEPENDPATH += . +LIBS = +OBJECTS_DIR = . + +cross_compile { + equals(QT_ARCH, arm): V8_TARGET_ARCH = arm +} + +include(../../v8/v8.pri) + +cross_compile { + equals(V8_TARGET_ARCH, arm): SOURCES += $$V8SRC/arm/simulator-arm.cc +} + +SOURCES += \ + $$V8SRC/snapshot-empty.cc \ + $$V8SRC/mksnapshot.cc + +unix:LIBS += -lpthread + +# We don't need to install this tool, it's only used for building v8. diff --git a/src/tools/tools.pro b/src/tools/tools.pro index 5cbe92309e..89ce0be055 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -2,6 +2,7 @@ TEMPLATE = subdirs TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc !contains(QT_CONFIG, no-gui): TOOLS_SUBDIRS += src_tools_uic +contains(QT_CONFIG, v8):contains(QT_CONFIG, v8snapshot): TOOLS_SUBDIRS += src_tools_mkv8snapshot # Set subdir and respective target name src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/tools/bootstrap src_tools_bootstrap.target = sub-tools-bootstrap @@ -11,6 +12,8 @@ src_tools_rcc.subdir = $$QT_SOURCE_TREE/src/tools/rcc src_tools_rcc.target = sub-rcc src_tools_uic.subdir = $$QT_SOURCE_TREE/src/tools/uic src_tools_uic.target = sub-uic +src_tools_mkv8snapshot.subdir = $$QT_SOURCE_TREE/src/tools/mkv8snapshot +src_tools_mkv8snapshot.target = sub-mkv8snapshot !wince*:!ordered { # Set dependencies for each subdir diff --git a/src/v8/v8.pri b/src/v8/v8.pri index 868bbad207..26feca9b34 100644 --- a/src/v8/v8.pri +++ b/src/v8/v8.pri @@ -5,16 +5,19 @@ isEmpty(QT_ARCH) { load(qt_config) } -equals(QT_ARCH, x86_64)|contains(CONFIG, x86_64):CONFIG += arch_x86_64 -else:equals(QT_ARCH, "i386"):CONFIG += arch_i386 -else:equals(QT_ARCH, "arm"):CONFIG += arch_arm -else:equals(QMAKE_HOST.arch, armv7l):CONFIG += arch_arm -else:equals(QMAKE_HOST.arch, armv5tel):CONFIG += arch_arm -else:equals(QMAKE_HOST.arch, x86_64):CONFIG += arch_x86_64 -else:equals(QMAKE_HOST.arch, x86):CONFIG += arch_i386 -else:equals(QMAKE_HOST.arch, i386):CONFIG += arch_i386 -else:equals(QMAKE_HOST.arch, i686):CONFIG += arch_i386 -else:error("Couldn't detect supported architecture ($$QMAKE_HOST.arch/$$QT_ARCH). Currently supported architectures are: x64, x86 and arm") +isEmpty(V8_TARGET_ARCH) { + # Detect target + equals(QT_ARCH, x86_64)|contains(CONFIG, x86_64):V8_TARGET_ARCH = x64 + else:equals(QT_ARCH, "i386"): V8_TARGET_ARCH = ia32 + else:equals(QT_ARCH, "arm"): V8_TARGET_ARCH = arm + else:equals(QMAKE_HOST.arch, armv7l): V8_TARGET_ARCH = arm + else:equals(QMAKE_HOST.arch, armv5tel): V8_TARGET_ARCH = arm + else:equals(QMAKE_HOST.arch, x86_64): V8_TARGET_ARCH = x64 + else:equals(QMAKE_HOST.arch, x86): V8_TARGET_ARCH = ia32 + else:equals(QMAKE_HOST.arch, i386): V8_TARGET_ARCH = ia32 + else:equals(QMAKE_HOST.arch, i686): V8_TARGET_ARCH = ia32 + else:error("Couldn't detect supported v8 architecture ($$QMAKE_HOST.arch/$$QT_ARCH). Currently supported architectures are: x64, x86 and arm") +} include($$PWD/v8base.pri) @@ -23,8 +26,6 @@ include($$PWD/v8base.pri) CONFIG(debug, debug|release):V8_GENERATED_SOURCES_DIR = generated-debug else: V8_GENERATED_SOURCES_DIR = generated-release -!contains(QT_CONFIG, static): DEFINES += V8_SHARED BUILDING_V8_SHARED - # this maybe removed in future DEFINES += ENABLE_DEBUGGER_SUPPORT @@ -145,10 +146,7 @@ SOURCES += \ $$V8SRC/extensions/gc-extension.cc \ $$V8SRC/extensions/externalize-string-extension.cc -SOURCES += \ - $$V8SRC/snapshot-empty.cc \ - -arch_arm { +equals(V8_TARGET_ARCH, arm) { DEFINES += V8_TARGET_ARCH_ARM SOURCES += \ $$V8SRC/arm/builtins-arm.cc \ @@ -169,9 +167,7 @@ SOURCES += \ $$V8SRC/arm/regexp-macro-assembler-arm.cc \ $$V8SRC/arm/stub-cache-arm.cc \ $$V8SRC/arm/assembler-arm.cc -} - -arch_i386 { +} else:equals(V8_TARGET_ARCH, ia32) { DEFINES += V8_TARGET_ARCH_IA32 SOURCES += \ $$V8SRC/ia32/assembler-ia32.cc \ @@ -191,10 +187,8 @@ SOURCES += \ $$V8SRC/ia32/macro-assembler-ia32.cc \ $$V8SRC/ia32/regexp-macro-assembler-ia32.cc \ $$V8SRC/ia32/stub-cache-ia32.cc -} - -# FIXME Should we use QT_CONFIG instead? What about 32 bit Macs? -arch_x86_64 { +} else:equals(V8_TARGET_ARCH, x64) { +# FIXME What about 32-bit Macs? DEFINES += V8_TARGET_ARCH_X64 SOURCES += \ $$V8SRC/x64/assembler-x64.cc \ diff --git a/src/v8/v8.pro b/src/v8/v8.pro index ae43f244cf..1bc542ee32 100644 --- a/src/v8/v8.pro +++ b/src/v8/v8.pro @@ -22,4 +22,20 @@ INCLUDEPATH -= $$MODULE_INCLUDES $$MODULE_INCLUDES/.. HEADERS += $$QT_SOURCE_TREE/src/v8/qtv8version.h +!contains(QT_CONFIG, static): DEFINES += V8_SHARED BUILDING_V8_SHARED + include(v8.pri) + +contains(QT_CONFIG, v8snapshot) { + mkv8snapshot.commands = ../../bin/mkv8snapshot ${QMAKE_FILE_OUT} + DUMMY_FILE = v8.pro + mkv8snapshot.input = DUMMY_FILE + mkv8snapshot.output = $$V8_GENERATED_SOURCES_DIR/snapshot.cpp + mkv8snapshot.variable_out = SOURCES + mkv8snapshot.dependency_type = TYPE_C + mkv8snapshot.name = generating[v8] ${QMAKE_FILE_IN} + silent:mkv8snapshot.commands = @echo generating[v8] ${QMAKE_FILE_IN} && $$mkv8snapshot.commands + QMAKE_EXTRA_COMPILERS += mkv8snapshot +} else { + SOURCES += $$V8SRC/snapshot-empty.cc +} diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 2bd129139c..1048512691 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -255,6 +255,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "DIRECTSHOW" ] = "no"; dictionary[ "WEBKIT" ] = "auto"; dictionary[ "V8" ] = "yes"; + dictionary[ "V8SNAPSHOT" ] = "auto"; dictionary[ "DECLARATIVE" ] = "auto"; dictionary[ "DECLARATIVE_DEBUG" ]= "yes"; dictionary[ "PLUGIN_MANIFESTS" ] = "yes"; @@ -2057,6 +2058,8 @@ bool Configure::checkAvailability(const QString &part) available = findFile("wmsdk.h"); } else if (part == "MULTIMEDIA" || part == "SCRIPT" || part == "SCRIPTTOOLS" || part == "V8" || part == "DECLARATIVE") { available = true; + } else if (part == "V8SNAPSHOT") { + available = true; } else if (part == "WEBKIT") { available = (dictionary.value("QMAKESPEC") == "win32-msvc2005") || (dictionary.value("QMAKESPEC") == "win32-msvc2008") || (dictionary.value("QMAKESPEC") == "win32-msvc2010") || (dictionary.value("QMAKESPEC") == "win32-g++"); if (dictionary[ "SHARED" ] == "no") { @@ -2156,6 +2159,8 @@ void Configure::autoDetection() dictionary["WEBKIT"] = checkAvailability("WEBKIT") ? "yes" : "no"; if (dictionary["V8"] == "auto") dictionary["V8"] = checkAvailability("V8") ? "yes" : "no"; + if (dictionary["V8SNAPSHOT"] == "auto") + dictionary["V8SNAPSHOT"] = (dictionary["V8"] == "yes") && checkAvailability("V8SNAPSHOT") ? "yes" : "no"; if (dictionary["DECLARATIVE"] == "auto") dictionary["DECLARATIVE"] = dictionary["V8"] == "yes" ? "yes" : "no"; if (dictionary["DECLARATIVE_DEBUG"] == "auto") @@ -2545,8 +2550,11 @@ void Configure::generateOutputVars() // We currently have no switch for QtSvg, so add it unconditionally. qtConfig += "svg"; - if (dictionary[ "V8" ] == "yes") + if (dictionary[ "V8" ] == "yes") { qtConfig += "v8"; + if (dictionary[ "V8SNAPSHOT" ] == "yes") + qtConfig += "v8snapshot"; + } // Add config levels -------------------------------------------- QStringList possible_configs = QStringList() -- cgit v1.2.3