13
13
#include " base/task.h"
14
14
#include " chrome/common/chrome_switches.h"
15
15
#include " chrome/common/process_watcher.h"
16
+ #include " mozilla/ProcessType.h"
16
17
#ifdef MOZ_WIDGET_COCOA
17
18
# include < bsm/libbsm.h>
18
19
# include < mach/mach_traps.h>
66
67
#ifdef XP_WIN
67
68
# include < stdlib.h>
68
69
70
+ # include " mozilla/WindowsVersion.h"
69
71
# include " nsIWinTaskbar.h"
70
72
# define NS_TASKBAR_CONTRACTID " @mozilla.org/windows-taskbar;1"
71
73
@@ -249,7 +251,7 @@ class BaseProcessLauncher {
249
251
};
250
252
251
253
#ifdef XP_WIN
252
- class WindowsProcessLauncher : public BaseProcessLauncher {
254
+ class WindowsProcessLauncher final : public BaseProcessLauncher {
253
255
public:
254
256
WindowsProcessLauncher (GeckoChildProcessHost* aHost,
255
257
std::vector<std::string>&& aExtraOpts)
@@ -261,6 +263,9 @@ class WindowsProcessLauncher : public BaseProcessLauncher {
261
263
virtual RefPtr<ProcessHandlePromise> DoLaunch () override ;
262
264
virtual Result<Ok, LaunchError> DoFinishLaunch () override ;
263
265
266
+ private:
267
+ void AddApplicationPrefetchArgument ();
268
+
264
269
mozilla::Maybe<CommandLine> mCmdLine ;
265
270
bool mUseSandbox = false ;
266
271
@@ -1401,6 +1406,97 @@ Result<Ok, LaunchError> MacProcessLauncher::DoFinishLaunch() {
1401
1406
#endif // XP_MACOSX
1402
1407
1403
1408
#ifdef XP_WIN
1409
+ void WindowsProcessLauncher::AddApplicationPrefetchArgument () {
1410
+ // The Application Launch Prefetcher (ALPF) is an ill-documented Windows
1411
+ // subsystem that's intended to speed up process launching, apparently mostly
1412
+ // by assuming that a binary is going to want to load the same DLLs as it did
1413
+ // the last time it launched, and getting those prepped for loading as well.
1414
+ //
1415
+ // For most applications, that's a good bet. For Firefox, it's less so, since
1416
+ // we use the same binary with different arguments to do completely different
1417
+ // things. Windows does allow applications to take up multiple slots in this
1418
+ // cache, but the "which bucket does this invocation go in?" mechanism is
1419
+ // highly unusual: the OS scans the command line and looks for a command-line
1420
+ // switch of a particular form.
1421
+ //
1422
+ // (There is allegedly a way to do this without involving the command line,
1423
+ // OVERRIDE_PREFETCH_PARAMETER, but it's even more poorly documented.)
1424
+
1425
+ // Applications' different prefetch-cache buckets are named with numbers from
1426
+ // "1" to some OS-version-determined limit, with an additional implicit "0"
1427
+ // cache bucket which is used when no valid prefetch cache slot is named.
1428
+ //
1429
+ // (The "0" bucket's existence and behavior is not documented, but has been
1430
+ // confirmed by observing the creation and enumeration of cache files in the
1431
+ // C:\Windows\Prefetch folder.)
1432
+ static size_t const kMaxSlotNo = IsWin1122H2OrLater () ? 16 : 8 ;
1433
+
1434
+ // Determine the prefetch-slot number to be used for the process we're about
1435
+ // to launch.
1436
+ //
1437
+ // This may be changed freely between Firefox versions, as a Firefox update
1438
+ // will completely invalidate the prefetch cache anyway.
1439
+ size_t const prefetchSlot = [&]() -> size_t {
1440
+ switch (mProcessType ) {
1441
+ // This code path is not used when starting the main process...
1442
+ case GeckoProcessType_Default:
1443
+ // ...ForkServer is not used on Windows...
1444
+ case GeckoProcessType_ForkServer:
1445
+ // ..."End" isn't a process-type, just a limit...
1446
+ case GeckoProcessType_End:
1447
+ // ...and any new process-types should be considered explicitly here.
1448
+ default :
1449
+ MOZ_ASSERT_UNREACHABLE (" Invalid process type" );
1450
+ return 0 ;
1451
+
1452
+ // We reserve 1 for the main process as started by the launcher process.
1453
+ // (See LauncherProcessWin.cpp.) Otherwise, we mostly match the process-
1454
+ // type enumeration.
1455
+ case GeckoProcessType_Content:
1456
+ return 2 ;
1457
+ case GeckoProcessType_Socket:
1458
+ return 3 ; // usurps IPDLUnitTest
1459
+ case GeckoProcessType_GMPlugin:
1460
+ return 4 ;
1461
+ case GeckoProcessType_GPU:
1462
+ return 5 ;
1463
+ case GeckoProcessType_RemoteSandboxBroker:
1464
+ return 6 ; // usurps VR
1465
+ case GeckoProcessType_RDD:
1466
+ return 7 ;
1467
+
1468
+ case GeckoProcessType_Utility: {
1469
+ // Continue the enumeration, using the SandboxingKind as a
1470
+ // probably-passably-precise proxy for the process's purpose.
1471
+ //
1472
+ // (On Win10 and earlier, or when sandboxing is not used, this will lump
1473
+ // all utility processes into slot 8.)
1474
+ # ifndef MOZ_SANDBOX
1475
+ size_t const val = 0 ;
1476
+ # else
1477
+ size_t const val = static_cast <size_t >(mSandbox );
1478
+ # endif
1479
+ return std::min (kMaxSlotNo , 8 + val);
1480
+ }
1481
+
1482
+ // These process types are started so rarely that we're not concerned
1483
+ // about their interaction with the prefetch cache. Lump them together at
1484
+ // the end (possibly alongside other process types).
1485
+ case GeckoProcessType_IPDLUnitTest:
1486
+ case GeckoProcessType_VR:
1487
+ return kMaxSlotNo ;
1488
+ }
1489
+ }();
1490
+ MOZ_ASSERT (prefetchSlot <= kMaxSlotNo );
1491
+
1492
+ if (prefetchSlot == 0 ) {
1493
+ // default; no explicit argument needed
1494
+ return ;
1495
+ }
1496
+
1497
+ mCmdLine ->AppendLooseValue (StringPrintf (L" /prefetch:%zu" , prefetchSlot));
1498
+ }
1499
+
1404
1500
Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup () {
1405
1501
Result<Ok, LaunchError> aError = BaseProcessLauncher::DoSetup ();
1406
1502
if (aError.isErr ()) {
@@ -1581,6 +1677,9 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
1581
1677
// Process type
1582
1678
mCmdLine ->AppendLooseValue (UTF8ToWide (ChildProcessType ()));
1583
1679
1680
+ // Prefetch cache hint
1681
+ AddApplicationPrefetchArgument ();
1682
+
1584
1683
# ifdef MOZ_SANDBOX
1585
1684
if (mUseSandbox ) {
1586
1685
// Mark the handles to inherit as inheritable.
0 commit comments