Skip to content

Commit

Permalink
Add V8 snapshot support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Lars Knoll <[email protected]>
  • Loading branch information
Kent Hansen authored and Qt by Nokia committed Nov 22, 2011
1 parent ce829cb commit 52ef2ee
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ bin/linguist*
bin/lrelease*
bin/lupdate*
bin/lconvert*
bin/mkv8snapshot*
bin/moc*
bin/makeqpf*
bin/pixeltool*
Expand Down
28 changes: 28 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions src/tools/mkv8snapshot/mkv8snapshot.pro
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 3 additions & 0 deletions src/tools/tools.pro
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
40 changes: 17 additions & 23 deletions src/v8/v8.pri
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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

Expand Down Expand Up @@ -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 \
Expand All @@ -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 \
Expand All @@ -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 \
Expand Down
16 changes: 16 additions & 0 deletions src/v8/v8.pro
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
10 changes: 9 additions & 1 deletion tools/configure/configureapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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") {
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 52ef2ee

Please sign in to comment.