diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 7149004..85a8481 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -884,7 +884,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
     $files[$type] = array();
   }
 
-  if (!empty($filename) && file_exists($filename)) {
+  if (!empty($filename)) {
     $files[$type][$name] = $filename;
   }
   elseif (isset($files[$type][$name])) {
@@ -938,7 +938,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
         // extension, not just the file we are currently looking for. This
         // prevents unnecessary scans from being repeated when this function is
         // called more than once in the same page request.
-        $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
+        $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir);
         foreach ($matches as $matched_name => $file) {
           $files[$type][$matched_name] = $file->uri;
         }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index b3dc9cb..cf50cca 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -5097,14 +5097,16 @@ function drupal_cron_cleanup() {
  * depending on what type of object you are looking for. For instance, if you
  * are looking for modules and call:
  * @code
- * drupal_system_listing("/\.module$/", "modules", 'name', 0);
+ * drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules');
  * @endcode
- * this function will search the site-wide modules directory (i.e., /modules/),
- * your installation profile's directory (i.e.,
- * /profiles/your_site_profile/modules/), the all-sites directory (i.e.,
- * /modules/), and your site-specific directory (i.e.,
- * /sites/your_site_dir/modules/), in that order, and return information about
- * all of the files ending in .module in those directories.
+ * this function will search:
+ * - the core modules directory; i.e., /core/modules
+ * - your installation profile's directory; e.g., /profiles/standard/modules
+ * - the site-wide modules directory; i.e., /modules
+ * - the all-sites directory; i.e., /sites/all/modules
+ * - the site-specific directory; i.e., /sites/example.com/modules
+ * in that order, and return information about all of the files ending in
+ * .module in those directories.
  *
  * The information is returned in an associative array, which can be keyed on
  * the file name ($key = 'filename'), the file name without the extension ($key
@@ -5115,21 +5117,28 @@ function drupal_cron_cleanup() {
  * files found.
  *
  * @param string $mask
- *   The preg_match() regular expression for the files to find.
+ *   The preg_match() regular expression for the files to find. The expression
+ *   must be anchored and use DRUPAL_PHP_FUNCTION_PATTERN for the file name part
+ *   before the extension, since the results could contain matches that do not
+ *   present valid Drupal extensions otherwise.
  * @param string $directory
  *   The subdirectory name in which the files are found. For example,
- *   'core/modules' will search in sub-directories of the /core/modules
- *   directory, sub-directories of /modules/, etc.
+ *   'modules' will search all 'modules' directories and their sub-directories
+ *   as explained above.
  * @param string $key
- *   The key to be used for the associative array returned. Possible values are
- *   'uri', for the file's URI; 'filename', for the basename of the file; and
- *   'name' for the name of the file without the extension. If you choose 'name'
- *   or 'filename', only the highest-precedence file will be returned.
+ *   (optional) The key to be used for the associative array returned. Possible
+ *   values are:
+ *   - 'uri' for the file's URI.
+ *   - 'filename' for the basename of the file.
+ *   - 'name' for the name of the file without the extension.
+ *   For 'name' and 'filename' only the highest-precedence file is returned.
+ *   Defaults to 'name'.
  * @param int $min_depth
- *   Minimum depth of directories to return files from, relative to each
- *   directory searched. For instance, a minimum depth of 2 would find modules
- *   inside /core/modules/node/tests, but not modules directly in
- *   /core/modules/node.
+ *   (optional) Minimum depth of directories to return files from, relative to
+ *   each directory searched. For instance, a directory of 'modules' and a
+ *   minimum depth of 2 would find modules inside /modules/node/tests, but not
+ *   modules directly in /modules/node. Defaults to 1. The default is sufficient
+ *   and suitable for all extension types known by Drupal core.
  *
  * @return array
  *   An associative array of file objects, keyed on the chosen key. Each element
@@ -5179,7 +5188,12 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
     require_once DRUPAL_ROOT . '/core/includes/file.inc';
   }
   foreach ($searchdir as $dir) {
-    $files_to_add = file_scan_directory($dir, $mask, array('key' => $key, 'min_depth' => $min_depth));
+    $files_to_add = file_scan_directory($dir, $mask, array(
+      'key' => $key,
+      'min_depth' => $min_depth,
+      // Do not recurse into ./lib directories; they cannot contain extensions.
+      'nomask' => '/^(CVS|lib)$/',
+    ));
 
     // Duplicate files found in later search directories take precedence over
     // earlier ones, so we want them to overwrite keys in our resulting
diff --git a/core/includes/file.inc b/core/includes/file.inc
index f1c6ac9..c167a54 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -1432,7 +1432,7 @@ function file_download() {
 function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
   // Merge in defaults.
   $options += array(
-    'nomask' => '/(\.\.?|CVS)$/',
+    'nomask' => '/^CVS$/',
     'callback' => 0,
     'recurse' => TRUE,
     'key' => 'uri',
@@ -1443,6 +1443,7 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
   $files = array();
   if (is_dir($dir) && $handle = opendir($dir)) {
     while (FALSE !== ($filename = readdir($handle))) {
+      // Skip this file if it matches the nomask or starts with a dot.
       if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') {
         $uri = "$dir/$filename";
         $uri = file_stream_wrapper_uri_normalize($uri);
diff --git a/core/includes/install.inc b/core/includes/install.inc
index db92987..5e56c47 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -368,7 +368,7 @@ function drupal_verify_profile($install_state) {
 
   // Get a list of modules that exist in Drupal's assorted subdirectories.
   $present_modules = array();
-  foreach (drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0) as $present_module) {
+  foreach (drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules') as $present_module) {
     $present_modules[] = $present_module->name;
   }
 
diff --git a/core/includes/module.inc b/core/includes/module.inc
index 5a17873..392376c 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -992,7 +992,7 @@ function module_invoke_all($hook) {
  * Returns an array of modules required by core.
  */
 function drupal_required_modules() {
-  $files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'modules', 'name', 0);
+  $files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'modules');
   $required = array();
 
   // An installation profile is required and one must always be loaded.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 307be21..05d06ae 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -863,7 +863,7 @@ protected function tearDown() {
 
     // Reset module list and module load status.
     module_list_reset();
-    module_load_all(FALSE, TRUE);
+    module_load_all(NULL, TRUE);
 
     // Restore original in-memory configuration.
     $conf = $this->originalConf;
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 2388601..0acc8b3 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -385,10 +385,20 @@ function simpletest_test_get_all() {
  * Registers namespaces for disabled modules.
  */
 function simpletest_classloader_register() {
-  $all_data = system_rebuild_module_data();
-  $all_data += system_rebuild_theme_data();
-  foreach ($all_data as $name => $data) {
-    drupal_classloader_register($name, dirname($data->filename));
+  // @see drupal_get_filename()
+  $types = array(
+    'theme_engine' => array('dir' => 'themes/engines', 'extension' => 'engine'),
+    'module' => array('dir' => 'modules', 'extension' => 'module'),
+    'theme' => array('dir' => 'themes', 'extension' => 'info'),
+    'profile' => array('dir' => 'profiles', 'extension' => 'profile'),
+  );
+  foreach ($types as $type => $info) {
+    $matches = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.' . $info['extension'] . '$/', $info['dir']);
+    foreach ($matches as $name => $file) {
+      drupal_classloader_register($name, dirname($file->uri));
+      // While being there, prime drupal_get_filename().
+      drupal_get_filename($type, $name, $file->uri);
+    }
   }
 }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
index 5c57009..2352c04 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
@@ -55,7 +55,7 @@ function testDirectoryPrecedence() {
 
     // Now scan the directories and check that the files take precedence as
     // expected.
-    $files = drupal_system_listing('/\.module$/', 'modules', 'name', 1);
+    $files = drupal_system_listing('/\.module$/', 'modules');
     foreach ($expected_directories as $module => $directories) {
       $expected_directory = array_shift($directories);
       $expected_filename = "$expected_directory/$module/$module.module";
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index bb3f2b4..dc7ed8a 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2726,10 +2726,10 @@ function system_get_module_info($property) {
  */
 function _system_rebuild_module_data() {
   // Find modules
-  $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0);
+  $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules');
 
   // Find installation profiles.
-  $profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles', 'name', 0);
+  $profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles');
 
   // Include the installation profile in modules that are loaded.
   $profile = drupal_get_profile();
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 2395a84..460ca19 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -190,6 +190,7 @@ function simpletest_script_parse_args() {
     'color' => FALSE,
     'verbose' => FALSE,
     'keep-results' => FALSE,
+    'profile' => FALSE,
     'test_names' => array(),
     // Used internally.
     'test-id' => 0,
@@ -408,7 +409,11 @@ function simpletest_script_run_one_test($test_id, $test_class) {
 function simpletest_script_command($test_id, $test_class) {
   global $args, $php;
 
-  $command = escapeshellarg($php) . ' ' . escapeshellarg('./core/scripts/' . $args['script']);
+  $command = escapeshellarg($php);
+  if ($args['profile']) {
+    $command .= ' -d xdebug.profiler_enable=On';
+  }
+  $command .= ' ' . escapeshellarg('./core/scripts/' . $args['script']);
   $command .= ' --url ' . escapeshellarg($args['url']);
   $command .= ' --php ' . escapeshellarg($php);
   $command .= " --test-id $test_id";
