Support caching host filesystem symlink targets to speedup DevFS updates (#6798)

diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 1001232..0249075 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -8,6 +8,7 @@
 
 import 'package:path/path.dart' as path;
 
+import 'base/context.dart';
 import 'build_info.dart';
 import 'dart/package_map.dart';
 import 'asset.dart';
@@ -16,6 +17,13 @@
 
 typedef void DevFSProgressReporter(int progress, int max);
 
+class DevFSConfig {
+  /// Should DevFS assume that symlink targets are stable?
+  bool cacheSymlinks = false;
+}
+
+DevFSConfig get devFSConfig => context[DevFSConfig];
+
 // A file that has been added to a DevFS.
 class DevFSEntry {
   DevFSEntry(this.devicePath, this.file)
@@ -30,10 +38,13 @@
   String get assetPath => bundleEntry.archivePath;
 
   final FileSystemEntity file;
+  FileSystemEntity _linkTarget;
   FileStat _fileStat;
   // When we scanned for files, did this still exist?
   bool _exists = false;
   DateTime get lastModified => _fileStat?.modified;
+  bool get _isSourceEntry => file == null;
+  bool get _isAssetEntry => bundleEntry != null;
   bool get stillExists {
     if (_isSourceEntry)
       return true;
@@ -67,19 +78,28 @@
   void _stat() {
     if (_isSourceEntry)
       return;
+    if (_linkTarget != null) {
+      // Stat the cached symlink target.
+      _fileStat = _linkTarget.statSync();
+      return;
+    }
     _fileStat = file.statSync();
     if (_fileStat.type == FileSystemEntityType.LINK) {
-      // Stat the link target.
+      // Resolve, stat, and maybe cache the symlink target.
       String resolved = file.resolveSymbolicLinksSync();
-      _fileStat = FileStat.statSync(resolved);
+      FileSystemEntity linkTarget = new File(resolved);
+      // Stat the link target.
+      _fileStat = linkTarget.statSync();
+      if (devFSConfig.cacheSymlinks) {
+        _linkTarget = linkTarget;
+      }
     }
   }
 
-  bool get _isSourceEntry => file == null;
-
-  bool get _isAssetEntry => bundleEntry != null;
-
   File _getFile() {
+    if (_linkTarget != null) {
+      return _linkTarget;
+    }
     if (file is Link) {
       // The link target.
       return new File(file.resolveSymbolicLinksSync());