0

Infrastructure for enabling V8's initial snapshot to be loaded from external files as opposed to being statically linked to the binary.

This is not currently supported on any architecture.

BUG=421063

Review URL: https://codereview.chromium.org/594603003

Cr-Commit-Position: refs/heads/master@{#301595}
This commit is contained in:
baixo
2014-10-28 04:52:21 -07:00
committed by Commit bot
parent fb8875c804
commit 3a3c88a61f
52 changed files with 495 additions and 19 deletions
android_webview
android_webview_tests.gypi
test
shell
src
org
chromium
android_webview
base/android/java/src/org/chromium/base
build
chrome
components
content
gin
net
testing/android/java/src/org/chromium/native_test
third_party/android_webview_glue
tools

@ -35,6 +35,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
'copies': [
@ -55,7 +61,13 @@
'files': [
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
}],
['v8_use_external_startup_data==1', {
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
],

@ -21,7 +21,9 @@ public class AwShellApplication extends Application {
private static final String TAG = "AwShellApplication";
/** The minimum set of .pak files the test runner needs. */
private static final String[] MANDATORY_PAKS = { "icudtl.dat" };
private static final String[] MANDATORY_PAKS = { "icudtl.dat",
"natives_blob.bin",
"snapshot_blob.bin" };
@Override
public void onCreate() {

@ -36,6 +36,8 @@ public class ResourceExtractor {
private static final String LAST_LANGUAGE = "Last language";
private static final String PAK_FILENAMES = "Pak filenames";
private static final String ICU_DATA_FILENAME = "icudtl.dat";
private static final String V8_NATIVES_DATA_FILENAME = "natives_blob.bin";
private static final String V8_SNAPSHOT_DATA_FILENAME = "snapshot_blob.bin";
private static String[] sMandatoryPaks = null;
@ -111,8 +113,11 @@ public class ResourceExtractor {
if (!paksToInstall.matcher(file).matches()) {
continue;
}
boolean isICUData = file.equals(ICU_DATA_FILENAME);
File output = new File(isICUData ? getAppDataDir() : outputDir, file);
boolean isAppDataFile = file.equals(ICU_DATA_FILENAME)
|| file.equals(V8_NATIVES_DATA_FILENAME)
|| file.equals(V8_SNAPSHOT_DATA_FILENAME);
File output = new File(isAppDataFile
? getAppDataDir() : outputDir, file);
if (output.exists()) {
continue;
}
@ -138,10 +143,11 @@ public class ResourceExtractor {
throw new IOException(file + " extracted with 0 length!");
}
if (!isICUData) {
if (!isAppDataFile) {
filenames.add(file);
} else {
// icudata needs to be accessed by a renderer process.
// icu and V8 data need to be accessed by a renderer
// process.
output.setReadable(true, false);
}
} finally {
@ -274,18 +280,21 @@ public class ResourceExtractor {
* running the tests.
*/
@VisibleForTesting
public void setExtractAllPaksForTesting() {
List<String> pakFileAssets = new ArrayList<String>();
public void setExtractAllPaksAndV8SnapshotForTesting() {
List<String> pakAndSnapshotFileAssets = new ArrayList<String>();
AssetManager manager = mContext.getResources().getAssets();
try {
String[] files = manager.list("");
for (String file : files) {
if (file.endsWith(".pak")) pakFileAssets.add(file);
if (file.endsWith(".pak")) pakAndSnapshotFileAssets.add(file);
}
} catch (IOException e) {
Log.w(LOGTAG, "Exception while accessing assets: " + e.getMessage(), e);
}
setMandatoryPaksToExtract(pakFileAssets.toArray(new String[pakFileAssets.size()]));
pakAndSnapshotFileAssets.add("natives_blob.bin");
pakAndSnapshotFileAssets.add("snapshot_blob.bin");
setMandatoryPaksToExtract(pakAndSnapshotFileAssets.toArray(
new String[pakAndSnapshotFileAssets.size()]));
}
private ResourceExtractor(Context context) {
@ -340,15 +349,27 @@ public class ResourceExtractor {
/**
* Pak files (UI strings and other resources) should be updated along with
* Chrome. A version mismatch can lead to a rather broken user experience.
* The ICU data (icudtl.dat) is less version-sensitive, but still can
* lead to malfunction/UX misbehavior. So, we regard failing to update them
* as an error.
* Failing to update the V8 snapshot files will lead to a version mismatch
* between V8 and the loaded snapshot which will cause V8 to crash, so this
* is treated as an error. The ICU data (icudtl.dat) is less
* version-sensitive, but still can lead to malfunction/UX misbehavior. So,
* we regard failing to update them as an error.
*/
private void deleteFiles() {
File icudata = new File(getAppDataDir(), ICU_DATA_FILENAME);
if (icudata.exists() && !icudata.delete()) {
Log.e(LOGTAG, "Unable to remove the icudata " + icudata.getName());
}
File v8_natives = new File(getAppDataDir(), V8_NATIVES_DATA_FILENAME);
if (v8_natives.exists() && !v8_natives.delete()) {
Log.e(LOGTAG,
"Unable to remove the v8 data " + v8_natives.getName());
}
File v8_snapshot = new File(getAppDataDir(), V8_SNAPSHOT_DATA_FILENAME);
if (v8_snapshot.exists() && !v8_snapshot.delete()) {
Log.e(LOGTAG,
"Unable to remove the v8 data " + v8_snapshot.getName());
}
File dir = getOutputDir();
if (dir.exists()) {
File[] files = dir.listFiles();

@ -122,6 +122,7 @@ def _GenerateDepsDirUsingIsolate(suite_name, isolate_file_path=None):
'--config-variable', 'fastbuild', '0',
'--config-variable', 'icu_use_data_file_flag', '1',
'--config-variable', 'libpeer_target_type', 'static_library',
'--config-variable', 'v8_use_external_startup_data', '0',
'--config-variable', 'lsan', '0',
# TODO(maruel): This may not be always true.
'--config-variable', 'target_arch', 'arm',

@ -1004,6 +1004,14 @@
}, {
'optimize_jni_generation%': 0,
}],
# TODO(baixo): Enable v8_use_external_startup_data
# http://crbug.com/421063
['android_webview_build==0 and android_webview_telemetry_build==0 and chromecast==0', {
'v8_use_external_startup_data': 0,
}, {
'v8_use_external_startup_data': 0,
}],
],
# Set this to 1 to enable use of concatenated impulse responses
@ -1205,6 +1213,7 @@
'video_hole%': '<(video_hole)',
'enable_load_completion_hacks%': '<(enable_load_completion_hacks)',
'support_pre_M6_history_database%': '<(support_pre_M6_history_database)',
'v8_use_external_startup_data': '<(v8_use_external_startup_data)',
# Whether or not we are building the Athena shell.
'use_athena%': '0',
@ -2925,6 +2934,9 @@
['enable_load_completion_hacks==1', {
'defines': ['ENABLE_LOAD_COMPLETION_HACKS=1'],
}],
['v8_use_external_startup_data==1', {
'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'],
}],
], # conditions for 'target_defaults'
'target_conditions': [
['<(use_openssl)==1', {

@ -85,6 +85,7 @@
'--config-variable',
'internal_gles2_conform_tests=<(internal_gles2_conform_tests)',
'--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
'--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
'--config-variable', 'lsan=<(lsan)',
'--config-variable', 'libpeer_target_type=<(libpeer_target_type)',
'--config-variable', 'use_openssl=<(use_openssl)',

@ -31,12 +31,18 @@ public class ChromeShellApplication extends ChromiumApplication {
* for its operation. We used to link the data statically to our binary,
* but don't do that any more and need to install along with pak files.
* See src/third_party/icu/README.chromium.
*
* V8's initial snapshot used to be statically linked to the binary, but
* now it's loaded from external files. Therefore we need to install such
* snapshots (natives_blob.bin and snapshot.bin) along with pak files.
*/
private static final String[] CHROME_MANDATORY_PAKS = {
"en-US.pak",
"resources.pak",
"chrome_100_percent.pak",
"icudtl.dat",
"natives_blob.bin",
"snapshot_blob.bin"
};
private static final String COMMAND_LINE_FILE = "/data/local/tmp/chrome-shell-command-line";

@ -2503,6 +2503,26 @@ void ChromeContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
mappings->Transfer(kAndroidICUDataDescriptor,
base::ScopedFD(icudata_file.TakePlatformFile()));
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
base::FilePath v8_data_path;
PathService::Get(base::DIR_ANDROID_APP_DATA, &v8_data_path);
DCHECK(!v8_data_path.empty());
int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
base::FilePath v8_natives_data_path =
v8_data_path.AppendASCII("natives_blob.bin");
base::FilePath v8_snapshot_data_path =
v8_data_path.AppendASCII("snapshot_blob.bin");
base::File v8_natives_data_file(v8_natives_data_path, file_flags);
base::File v8_snapshot_data_file(v8_snapshot_data_path, file_flags);
DCHECK(v8_natives_data_file.IsValid());
DCHECK(v8_snapshot_data_file.IsValid());
mappings->Transfer(kV8NativesDataDescriptor,
base::ScopedFD(v8_natives_data_file.TakePlatformFile()));
mappings->Transfer(kV8SnapshotDataDescriptor,
base::ScopedFD(v8_snapshot_data_file.TakePlatformFile()));
#endif // V8_USE_EXTERNAL_STARTUP_DATA
#else
int crash_signal_fd = GetCrashSignalFD(command_line);
if (crash_signal_fd >= 0) {

@ -45,6 +45,15 @@
'rule_name': 'js2webui',
'extension': 'unitjs',
'msvs_external_rule': 1,
'variables': {
'conditions': [
['v8_use_external_startup_data==1', {
'external_v8': 'y',
}, {
'external_v8': 'n',
}],
],
},
'inputs': [
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
@ -65,6 +74,7 @@
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
'--deps_js', '<(chromevox_test_deps_js_file)',
'--external', '<(external_v8)',
'<(mock_js)',
'<(test_api_js)',
'<(js2gtest)',
@ -80,6 +90,15 @@
'rule_name': 'js2extension',
'extension': 'extjs',
'msvs_external_rule': 1,
'variables': {
'conditions': [
['v8_use_external_startup_data==1', {
'external_v8': 'y',
}, {
'external_v8': 'n',
}],
],
},
'inputs': [
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
@ -98,6 +117,7 @@
'python',
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
'--external', '<(external_v8)',
'<(mock_js)',
'<(test_api_js)',
'<(js2gtest)',

@ -94,5 +94,6 @@
],
'includes': [
'angle.isolate',
'../gin/v8.isolate',
],
}

@ -109,6 +109,16 @@
'<(chrome_android_pak_output_folder)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'chrome_android_pak_input_resources': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
'chrome_android_pak_output_resources': [
'<(chrome_android_pak_output_folder)/natives_blob.bin',
'<(chrome_android_pak_output_folder)/snapshot_blob.bin',
],
}],
],
},
}

@ -1880,6 +1880,15 @@
'rule_name': 'js2webui',
'extension': 'js',
'msvs_external_rule': 1,
'variables': {
'conditions': [
['v8_use_external_startup_data==1', {
'external_v8': 'y',
}, {
'external_v8': 'n',
}],
],
},
'inputs': [
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
@ -1895,6 +1904,7 @@
'action': [
'python',
'<@(_inputs)',
'--external', '<(external_v8)',
'webui',
'<(RULE_INPUT_PATH)',
'chrome/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).js',
@ -2450,6 +2460,15 @@
'rule_name': 'js2webui',
'extension': 'js',
'msvs_external_rule': 1,
'variables': {
'conditions': [
['v8_use_external_startup_data==1', {
'external_v8': 'y',
}, {
'external_v8': 'n',
}],
],
},
'inputs': [
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
@ -2466,6 +2485,7 @@
'python',
'<@(_inputs)',
'webui',
'--external', '<(external_v8)',
'<(RULE_INPUT_PATH)',
'chrome/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).js',
'<@(_outputs)',

@ -2851,6 +2851,23 @@
'variables': {
'test_suite_name': 'unit_tests',
'android_manifest_path': 'test/android/unit_tests_apk/AndroidManifest.xml',
'conditions': [
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
'copies': [
{
'destination': '<(PRODUCT_DIR)/unit_tests_apk/assets',
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
},
],
}],
],
},
'includes': [ '../build/apk_test.gypi' ],
},

@ -224,6 +224,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data == 1', {
'inputs': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
'inputs': [
'<(create_installer_archive_py_path)',

@ -122,5 +122,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -54,6 +54,15 @@
'rule_name': 'js2unit',
'extension': 'gtestjs',
'msvs_external_rule': 1,
'variables': {
'conditions': [
['v8_use_external_startup_data==1', {
'external_v8': 'y',
}, {
'external_v8': 'n',
}],
],
},
'inputs': [
'<(gypv8sh)',
'<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
@ -69,6 +78,7 @@
'action': [
'python',
'<@(_inputs)',
'--external', '<(external_v8)',
'unit',
'<(RULE_INPUT_PATH)',
'chrome/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).<(_extension)',

@ -98,5 +98,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -139,5 +139,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -17,5 +17,6 @@
],
'includes': [
'../third_party/icu/icu.isolate',
'../gin/v8.isolate',
],
}

@ -17,5 +17,6 @@
],
'includes': [
'../sandbox/sandbox_linux_unittests.isolate',
'../gin/v8.isolate',
],
}

@ -1,4 +1,6 @@
include_rules = [
"+content",
# For loading V8's initial snapshot from external files.
"+gin/public/isolate_holder.h",
"+media/base", # For initializing media library.
]

@ -50,6 +50,10 @@
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
#if defined(OS_ANDROID)
#include "content/public/common/content_descriptors.h"
#endif
@ -716,9 +720,26 @@ class ContentMainRunnerImpl : public ContentMainRunner {
CHECK(base::i18n::InitializeICUWithFileDescriptor(icudata_fd));
else
CHECK(base::i18n::InitializeICU());
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
int v8_natives_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
kV8NativesDataDescriptor);
int v8_snapshot_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
kV8SnapshotDataDescriptor);
if (v8_natives_fd != -1 && v8_snapshot_fd != -1) {
CHECK(gin::IsolateHolder::LoadV8SnapshotFD(v8_natives_fd,
v8_snapshot_fd));
} else {
CHECK(gin::IsolateHolder::LoadV8Snapshot());
}
#endif // V8_USE_EXTERNAL_STARTUP_DATA
#else
CHECK(base::i18n::InitializeICU());
#endif
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
CHECK(gin::IsolateHolder::LoadV8Snapshot());
#endif // V8_USE_EXTERNAL_STARTUP_DATA
#endif // OS_ANDROID
InitializeStatsTable(command_line);

@ -575,6 +575,23 @@
}],
],
},
{
'target_name': 'content_v8_external_data',
'type': 'none',
'conditions': [
['v8_use_external_startup_data==1', {
'copies': [
{
'destination': '<(PRODUCT_DIR)/content_shell/assets',
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
},
],
}],
],
},
],
}], # OS == "android"
],

@ -124,5 +124,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -52,5 +52,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -1050,6 +1050,7 @@
'dependencies': [
'content.gyp:content_icudata',
'content.gyp:content_java',
'content.gyp:content_v8_external_data',
'content_java_test_support',
'content_shell_java',
'libcontent_shell_content_view',
@ -1075,6 +1076,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
'conditions': [

@ -337,7 +337,9 @@
}],
['OS=="android"', {
'dependencies': [
'../gin/gin.gyp:gin',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'content.gyp:content_v8_external_data',
],
}],
],
@ -1633,6 +1635,23 @@
],
'variables': {
'test_suite_name': 'content_unittests',
'conditions': [
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
'copies': [
{
'destination': '<(PRODUCT_DIR)/content_unittests_apk/assets',
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
},
],
}],
],
},
'includes': [ '../build/apk_test.gypi' ],
},
@ -1643,6 +1662,7 @@
'dependencies': [
'content.gyp:content_icudata',
'content.gyp:content_java',
'content.gyp:content_v8_external_data',
'content_browsertests',
'content_java_test_support',
'content_shell_java',
@ -1660,6 +1680,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
'includes': [ '../build/java_apk.gypi' ],
@ -1687,6 +1713,7 @@
'chromium_android_linker_test',
'content.gyp:content_icudata',
'content.gyp:content_java',
'content.gyp:content_v8_external_data',
'content_shell_java',
],
'variables': {
@ -1704,6 +1731,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
'includes': [ '../build/java_apk.gypi' ],

@ -114,5 +114,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -16,6 +16,12 @@ enum {
#if defined(OS_ANDROID)
kAndroidPropertyDescriptor,
kAndroidICUDataDescriptor,
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
kV8NativesDataDescriptor,
kV8SnapshotDataDescriptor,
#endif
#endif
// The first key that embedders can use to register descriptors (see

@ -9,6 +9,7 @@ specific_include_rules = {
".*\.cc": [
# Testing utilities can access anything in content/
"+content",
"+gin/public/isolate_holder.h",
"+media/base",
"+third_party/iaccessible2",
"+ui/base/resource/resource_bundle.h",

@ -37,6 +37,10 @@
#include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
#endif
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
namespace content {
class ContentTestSuiteBaseListener : public testing::EmptyTestEventListener {
@ -62,6 +66,10 @@ void ContentTestSuiteBase::Initialize() {
// by tests.
base::StatisticsRecorder::Initialize();
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
#if defined(OS_ANDROID)
// Register JNI bindings for android.
JNIEnv* env = base::android::AttachCurrentThread();

@ -16,7 +16,9 @@ public class ContentBrowserTestsApplication extends Application {
private static final String[] MANDATORY_PAK_FILES = new String[] {
"content_shell.pak",
"icudtl.dat"
"icudtl.dat",
"natives_blob.bin",
"snapshot_blob.bin"
};
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "content_shell";

@ -19,10 +19,16 @@ public class ChromiumLinkerTestApplication extends Application {
* operation. We use to link it statically to our binary, but not any more
* so that we have to install it along with other mandatory pak files.
* See src/third_party/icu/README.chromium.
*
* V8's initial snapshot used to be statically linked to the binary, but
* now it's loaded from external files. Therefore we need to install such
* snapshots (natives_blob.bin and snapshot.bin) along with pak files.
*/
private static final String[] MANDATORY_PAK_FILES = new String[] {
"content_shell.pak",
"icudtl.dat"
"icudtl.dat",
"natives_blob.bin",
"snapshot_blob.bin"
};
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "chromium_linker_test";

@ -22,10 +22,16 @@ public class ContentShellApplication extends ContentApplication {
* operation. We use to link it statically to our binary, but not any more
* so that we have to install it along with other mandatory pak files.
* See src/third_party/icu/README.chromium.
*
* V8's initial snapshot used to be statically linked to the binary, but
* now it's loaded from external files. Therefore we need to install such
* snapshots (natives_blob.bin and snapshot.bin) along with pak files.
*/
private static final String[] MANDATORY_PAK_FILES = new String[] {
"content_shell.pak",
"icudtl.dat"
"icudtl.dat",
"natives_blob.bin",
"snapshot_blob.bin"
};
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "content_shell";

@ -3,6 +3,8 @@ include_rules = [
"+chromeos/audio", # For WebRTC tests.
# Testing utilities can access anything in content/
"+content",
# For loading V8's initial snapshot from external files.
"+gin/public/isolate_holder.h",
"+media/audio", # For AudioParameters in WebRTC tests.
"+media/base", # For ChannelLayout in WebRTC tests.
"+ui/base/resource/data_pack.h",

@ -21,6 +21,10 @@
#include "media/base/media_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
#if defined(OS_ANDROID)
#include "base/message_loop/message_loop.h"
#include "content/app/mojo/mojo_init.h"
@ -53,6 +57,10 @@ class ContentBrowserTestSuite : public ContentTestSuiteBase {
base::i18n::AllowMultipleInitializeCallsForTesting();
base::i18n::InitializeICU();
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
// This needs to be done before base::TestSuite::Initialize() is called,
// as it also tries to set MessagePumpForUIFactory.
if (!base::MessageLoop::InitMessagePumpForUIFactory(

@ -38,6 +38,10 @@
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
namespace content {
TestBlinkWebUnitTestSupport::TestBlinkWebUnitTestSupport() {
@ -54,6 +58,10 @@ TestBlinkWebUnitTestSupport::TestBlinkWebUnitTestSupport() {
new base::StatsTable(base::StatsTable::TableIdentifier(), 20, 200));
base::StatsTable::set_current(stats_table_.get());
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
blink::initialize(this);
blink::mainThreadIsolate()->SetCounterFunction(
base::StatsTable::FindLocation);

@ -18,6 +18,11 @@
#include "gin/public/v8_platform.h"
#include "gin/run_microtasks_observer.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "base/files/memory_mapped_file.h"
#include "base/path_service.h"
#endif // V8_USE_EXTERNAL_STARTUP_DATA
namespace gin {
namespace {
@ -29,8 +34,70 @@ bool GenerateEntropy(unsigned char* buffer, size_t amount) {
return true;
}
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
base::MemoryMappedFile* g_mapped_natives = NULL;
base::MemoryMappedFile* g_mapped_snapshot = NULL;
bool MapV8Files(base::FilePath* natives_path, base::FilePath* snapshot_path,
int natives_fd = -1, int snapshot_fd = -1) {
int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
g_mapped_natives = new base::MemoryMappedFile;
if (!g_mapped_natives->IsValid()) {
if (natives_fd == -1
? !g_mapped_natives->Initialize(base::File(*natives_path, flags))
: !g_mapped_natives->Initialize(base::File(natives_fd))) {
delete g_mapped_natives;
g_mapped_natives = NULL;
LOG(FATAL) << "Couldn't mmap v8 natives data file";
return false;
}
}
g_mapped_snapshot = new base::MemoryMappedFile;
if (!g_mapped_snapshot->IsValid()) {
if (snapshot_fd == -1
? !g_mapped_snapshot->Initialize(base::File(*snapshot_path, flags))
: !g_mapped_snapshot->Initialize(base::File(snapshot_fd))) {
delete g_mapped_snapshot;
g_mapped_snapshot = NULL;
LOG(ERROR) << "Couldn't mmap v8 snapshot data file";
return false;
}
}
return true;
}
#endif // V8_USE_EXTERNAL_STARTUP_DATA
} // namespace
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
// static
bool IsolateHolder::LoadV8Snapshot() {
if (g_mapped_natives && g_mapped_snapshot)
return true;
base::FilePath data_path;
PathService::Get(base::DIR_ANDROID_APP_DATA, &data_path);
DCHECK(!data_path.empty());
base::FilePath natives_path = data_path.AppendASCII("natives_blob.bin");
base::FilePath snapshot_path = data_path.AppendASCII("snapshot_blob.bin");
return MapV8Files(&natives_path, &snapshot_path);
}
//static
bool IsolateHolder::LoadV8SnapshotFD(int natives_fd, int snapshot_fd) {
if (g_mapped_natives && g_mapped_snapshot)
return true;
return MapV8Files(NULL, NULL, natives_fd, snapshot_fd);
}
#endif // V8_USE_EXTERNAL_STARTUP_DATA
IsolateHolder::IsolateHolder() {
CHECK(g_array_buffer_allocator)
<< "You need to invoke gin::IsolateHolder::Initialize first";
@ -88,6 +155,19 @@ void IsolateHolder::Initialize(ScriptMode mode,
v8::V8::SetFlagsFromString(v8_flags, sizeof(v8_flags) - 1);
}
v8::V8::SetEntropySource(&GenerateEntropy);
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
v8::StartupData natives;
natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
natives.raw_size = g_mapped_natives->length();
natives.compressed_size = g_mapped_natives->length();
v8::V8::SetNativesDataBlob(&natives);
v8::StartupData snapshot;
snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data());
snapshot.raw_size = g_mapped_snapshot->length();
snapshot.compressed_size = g_mapped_snapshot->length();
v8::V8::SetSnapshotDataBlob(&snapshot);
#endif // V8_USE_EXTERNAL_STARTUP_DATA
v8::V8::Initialize();
v8_is_initialized = true;
}

@ -31,7 +31,9 @@ class GIN_EXPORT IsolateHolder {
~IsolateHolder();
// Should be invoked once before creating IsolateHolder instances to
// initialize V8 and Gin.
// initialize V8 and Gin. In case V8_USE_EXTERNAL_STARTUP_DATA is defined,
// V8's initial snapshot should be loaded (by calling LoadV8Snapshot or
// LoadV8SnapshotFD) before calling Initialize.
static void Initialize(ScriptMode mode,
v8::ArrayBuffer::Allocator* allocator);
@ -49,6 +51,13 @@ class GIN_EXPORT IsolateHolder {
// thread.
void RemoveRunMicrotasksObserver();
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#ifdef OS_ANDROID
static bool LoadV8SnapshotFD(int natives_fd, int snapshot_fd);
#endif
static bool LoadV8Snapshot();
#endif // V8_USE_EXTERNAL_STARTUP_DATA
private:
v8::Isolate* isolate_;
scoped_ptr<PerIsolateData> isolate_data_;

@ -60,6 +60,9 @@ int main(int argc, char** argv) {
base::AtExitManager at_exit;
CommandLine::Init(argc, argv);
base::i18n::InitializeICU();
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
gin::ArrayBufferAllocator::SharedInstance());

@ -10,6 +10,10 @@
#include "gin/public/isolate_holder.h"
#include "testing/gtest/include/gtest/gtest.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
using v8::Isolate;
using v8::Object;
using v8::Script;
@ -20,6 +24,10 @@ namespace gin {
TEST(RunnerTest, Run) {
std::string source = "this.result = 'PASS';\n";
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
gin::ArrayBufferAllocator::SharedInstance());
gin::IsolateHolder instance;

@ -19,6 +19,10 @@
#include "gin/try_catch.h"
#include "testing/gtest/include/gtest/gtest.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
namespace gin {
namespace {
@ -58,6 +62,10 @@ void RunTestFromFile(const base::FilePath& path, FileRunnerDelegate* delegate,
base::MessageLoop message_loop;
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
gin::ArrayBufferAllocator::SharedInstance());
gin::IsolateHolder instance;

@ -7,6 +7,10 @@
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
using v8::Context;
using v8::Local;
using v8::HandleScope;
@ -20,6 +24,9 @@ V8Test::~V8Test() {
}
void V8Test::SetUp() {
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
gin::ArrayBufferAllocator::SharedInstance());
instance_.reset(new gin::IsolateHolder);

15
gin/v8.isolate Normal file

@ -0,0 +1,15 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'conditions': [
['v8_use_external_startup_data==1', {
'variables': {
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
},
}],
],
}

@ -789,6 +789,11 @@
],
},
],
['v8_use_external_startup_data==1', {
'dependencies': [
'../gin/gin.gyp:gin',
]
}],
],
'target_conditions': [
# These source files are excluded by default platform rules, but they
@ -1651,6 +1656,23 @@
],
'variables': {
'test_suite_name': 'net_unittests',
'conditions': [
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
'copies': [
{
'destination': '<(PRODUCT_DIR)/net_unittests_apk/assets',
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
},
],
}],
],
},
'includes': [ '../build/apk_test.gypi' ],
},

@ -6,5 +6,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -42,5 +42,6 @@
],
'includes': [
'../base/base.isolate',
'../gin/v8.isolate',
],
}

@ -23,6 +23,10 @@
#include "net/proxy/proxy_resolver_v8.h"
#endif
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
#include "gin/public/isolate_holder.h"
#endif
using net::internal::ClientSocketPoolBaseHelper;
using net::SpdySession;
@ -57,6 +61,10 @@ int main(int argc, char** argv) {
// single-threaded.
net::EnableSSLServerSockets();
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
gin::IsolateHolder::LoadV8Snapshot();
#endif
#if !defined(OS_IOS)
net::ProxyResolverV8::EnsureIsolateCreated();
#endif

@ -36,7 +36,7 @@ public class ChromeNativeTestActivity extends Activity {
PathUtils.setPrivateDataDirectorySuffix("chrome");
ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext());
resourceExtractor.setExtractAllPaksForTesting();
resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting();
resourceExtractor.startExtractingResources();
resourceExtractor.waitForCompletion();

@ -19,6 +19,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'files': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
],

@ -31,6 +31,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
['v8_use_external_startup_data==1', {
'additional_input_paths': [
'<(PRODUCT_DIR)/natives_blob.bin',
'<(PRODUCT_DIR)/snapshot_blob.bin',
],
}],
],
},
'includes': [ '../../build/java_apk.gypi' ],

@ -26,6 +26,8 @@ def main ():
parser.add_option('--deps_js', action="store",
help=("Path to deps.js for dependency resolution, " +
"optional."))
parser.add_option('--external', action='store',
help="Load V8's initial snapshot from external files (y/n)")
(opts, args) = parser.parse_args()
if len(args) != 9:
@ -36,6 +38,12 @@ def main ():
icudatafile = os.path.join(os.path.dirname(v8_shell), 'icudtl.dat')
if os.path.exists(icudatafile):
cmd.extend(['--icu-data-file=%s' % icudatafile])
v8nativesfile = os.path.join(os.path.dirname(v8_shell), 'natives_blob.bin')
if opts.external == 'y' and os.path.exists(v8nativesfile):
cmd.extend(['--natives_blob=%s' % v8nativesfile])
v8snapshotfile = os.path.join(os.path.dirname(v8_shell), 'snapshot_blob.bin')
if opts.external == 'y' and os.path.exists(v8snapshotfile):
cmd.extend(['--snapshot_blob=%s' % v8snapshotfile])
arguments = [js2webui, inputfile, inputrelfile, opts.deps_js,
cxxoutfile, test_type]
cmd.extend(['-e', "arguments=" + json.dumps(arguments), mock_js,