diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 7daf311..5e79ea8 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -3541,3 +3541,42 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) {
   //   the operation.
   return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) >= parse_size($required)));
 }
+
+/**
+ * Instantiates and statically caches the correct class for a PHP loader.
+ *
+ * By default, this returns an instance of the
+ * Drupal\Component\PhpLoader\MTimeProtectedLoader class.
+ *
+ * Classes implementing Drupal\Component\PhpLoader\PhpLoaderInterface can
+ * register themselves both as a default implementation and for specific bins.
+ *
+ * @param $bin
+ *   The bin for which the loader object should be returned. Defaults to
+ *   'default'.
+ *
+ * @return Drupal\Component\PhpLoader\PhpLoaderInterface
+ *   The loader object associated with the specified bin.
+ *
+ * @see Drupal\Component\PhpLoader\PhpLoaderInterface
+ */
+function drupal_php_loader($bin = 'default') {
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['loader_objects'] = &drupal_static(__FUNCTION__);
+  }
+  $loader_objects = &$drupal_static_fast['loader_objects'];
+  if (!isset($loader_objects[$bin])) {
+    $loader_backends = variable_get('loader_classes', array('default' =>
+      array(
+        'class' => 'Drupal\Component\PhpLoader\MTimeProtectedLoader',
+        'prefix' => variable_get('file_public_path', conf_path() . '/files') . '/codegen',
+        'secret' => $GLOBALS['drupal_hash_salt'],
+      ),
+    ));
+    $loader = isset($loader_backends[$bin]) ? $loader_backends[$bin] : $loader_backends['default'];
+    $class = $loader['class'];
+    $loader_objects[$bin] = new $class($loader);
+  }
+  return $loader_objects[$bin];
+}
diff --git a/core/includes/file.inc b/core/includes/file.inc
index 133d64f..5f270e0 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -1325,6 +1325,8 @@ function file_unmanaged_delete($path) {
  *
  * @param $path
  *   A string containing either an URI or a file or directory path.
+ * @param $function
+ *   The function to recurse with. _simpletest_delete_recursive() uses this.
  *
  * @return
  *   TRUE for success or if path does not exist, FALSE in the event of an
@@ -1332,7 +1334,7 @@ function file_unmanaged_delete($path) {
  *
  * @see file_unmanaged_delete()
  */
-function file_unmanaged_delete_recursive($path) {
+function file_unmanaged_delete_recursive($path, $function = 'file_unmanaged_delete_recursive') {
   if (is_dir($path)) {
     $dir = dir($path);
     while (($entry = $dir->read()) !== FALSE) {
@@ -1340,7 +1342,7 @@ function file_unmanaged_delete_recursive($path) {
         continue;
       }
       $entry_path = $path . '/' . $entry;
-      file_unmanaged_delete_recursive($entry_path);
+      $function($entry_path, $function);
     }
     $dir->close();
 
diff --git a/core/lib/Drupal/Component/PhpLoader/MTimeProtectedLoader.php b/core/lib/Drupal/Component/PhpLoader/MTimeProtectedLoader.php
new file mode 100644
index 0000000..3fa96f1
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/MTimeProtectedLoader.php
@@ -0,0 +1,155 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Component\PhpLoader\MTimeProtectedLoader.
+ */
+namespace Drupal\Component\PhpLoader;
+
+/**
+ * Stores PHP files in a directory with  a secure hash filename.
+ *
+ * The hash is based on the directory mtime, a secret passed to the
+ * constructor and the filename itself. Because the actual filename gives no
+ * hint of what it contains, the holding directory name resembles the filename
+ * instead.
+ */
+class MTimeProtectedLoader implements PhpLoaderInterface {
+
+  /**
+   * The path to the directory containing the files.
+   *
+   * @var string
+   */
+  protected $prefix;
+
+  /**
+   * The secret used in the HMAC.
+   *
+   * @var string
+   */
+  protected $secret;
+
+  /**
+   * Constructs this MTimeProtectedLoader object.
+   *
+   * @param $config
+   *   An associated array, containing at least three keys (the rest are
+   *   ignored):
+   *   - prefix: The path to the directory containing the files.
+   *   - secret: A cryptographically hard to guess secret string.
+   */
+  public function __construct(array $config) {
+    $this->prefix = $config['prefix'];
+    $this->secret = $config['secret'];
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::includePhp()
+   */
+  public function includePhp($filename) {
+    $filename = str_replace('/', '#', $filename);
+    $dir = $this->prefix . '/' . $filename;
+    $filename = $this->getPath($dir, $filename, filemtime($dir));
+    if (file_exists($filename)) {
+      include_once $filename;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::write()
+   */
+  public function write($filename, $data) {
+    $filename = str_replace('/', '#', $filename);
+    $original_path = "$this->prefix/.$filename";
+    if (!file_exists($this->prefix)) {
+      mkdir($this->prefix, 0700, TRUE);
+      chmod($this->prefix, 0700);
+    }
+    if (!@file_put_contents($original_path, $data)) {
+      return FALSE;
+    }
+    chmod($original_path, 0400);
+    $dir = $this->prefix . '/' . $filename;
+    if (file_exists($dir)) {
+      $this->cleanDir($dir);
+      touch($dir);
+    }
+    else {
+      mkdir($dir);
+    }
+    $previous_mtime = 0;
+    $loop = 0;
+    // Now move the file to its final place. The mtime of a directory is the
+    // time of the last file create or delete in the directory. So the moving
+    // will update the directory mtime. This update will very likely not show
+    // up in filemtime, however, because it has a coarse, one second
+    //  granularity and typical moves takes significantly less than that. In
+    // the unlucky case it does, we need to redo the rename to a new filename
+    // because read() expects the filemtime to be less or equal to the
+    // directory mtime. So renaming needs to happen in a loop. Also note that
+    // clearstatcache() returns NULL so it does not affect the loop condition.
+    while (clearstatcache() || (($mtime = filemtime($dir)) && $previous_mtime != $mtime)) {
+      $previous_mtime = $mtime;
+      chmod($dir, 0300);
+      // Reset the file back in the original place if this is not the first
+      // iteration.
+      if ($loop) {
+        rename($full_path, $original_path);
+        // Make sure to not to have an infinite loop on a hopelessly slow
+        // filesystem.
+        if ($loop > 10) {
+          unlink($original_path);
+          return FALSE;
+        }
+      }
+      $full_path = $this->getPath($dir, $filename, $mtime);
+      rename($original_path, $full_path);
+      chmod($dir, 0100);
+      $loop++;
+    }
+    return TRUE;
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::delete()
+   */
+  public function delete($filename) {
+    $dir = $this->prefix . '/' . str_replace('/', '#', $filename);
+    $this->cleanDir($dir);
+    return rmdir($dir);
+  }
+
+  /**
+   * Removes everything in a directory, leaving it empty.
+   *
+   * @param $dir
+   *   The dir to be emptied out.
+   */
+  protected function cleanDir($dir) {
+    chmod($dir, 0700);
+    foreach (new DirectoryIterator($dir, FilesystemIterator::SKIP_DOTS) as $file) {
+      unlink($file->getPathName());
+    }
+  }
+
+  /**
+   * Constructs the secret path based on the filename and the mtime.
+   *
+   * This function returns a full path starting with $dir and ending in .php,
+   * the filename itself will be a secure hash based on $filename, the secret
+   * based to the constructor and $dir_mtime.
+   *
+   * @param string $dir
+   *   The directory containing the file.
+   * @param string $filename
+   *   The filename.
+   * @param int $dir_mtime
+   *   The mtime of $dir.
+   */
+  protected function getPath($dir, $filename, $dir_mtime) {
+    return $dir . '/' . hash_hmac('sha256', $filename, $this->secret . $dir_mtime) . '.php';
+  }
+}
diff --git a/core/lib/Drupal/Component/PhpLoader/NativeLoader.php b/core/lib/Drupal/Component/PhpLoader/NativeLoader.php
new file mode 100644
index 0000000..1963139
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/NativeLoader.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Component\PhpLoader\NativeLoader.
+ */
+
+namespace Drupal\Component\PhpLoader;
+
+/**
+ * The simplest PHP loader: just uses the native methods.
+ */
+class NativeLoader implements PhpLoaderInterface {
+
+  /**
+   * The path prefix where the files should be stored.
+   */
+  protected $prefix;
+
+
+  /**
+   * Constructs this NativeLoader object.
+   *
+   * @param $config
+   *   An associated array, containing at least one key (the rest are ignored):
+   *   - prefix: The path to the directory containing the files.
+   */
+  public function __construct(array $config) {
+    $this->prefix = $config['prefix'];
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::include()
+   */
+  public function includePhp($filename) {
+    $path = $this->prefix . '/' . $filename;
+    if (file_exists($path)) {
+      include_once $path;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::write()
+   */
+  public function write($filename, $data) {
+    $path = $this->prefix . '/' . $filename;
+    @mkdir(dirname($path), 0700, TRUE);
+    return (bool) file_put_contents($path, $data);
+  }
+
+  /**
+   * Implements Drupal\Component\PhpLoader\PhpLoaderInterface::delete()
+   */
+  public function delete($filename) {
+    return unlink($filename);
+  }
+}
diff --git a/core/lib/Drupal/Component/PhpLoader/PhpLoaderInterface.php b/core/lib/Drupal/Component/PhpLoader/PhpLoaderInterface.php
new file mode 100644
index 0000000..ad3acab
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/PhpLoaderInterface.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\PhpLoader\PhpLoaderInterface.
+ */
+
+namespace Drupal\Component\PhpLoader;
+
+/**
+ * Store PHP files.
+ */
+interface PhpLoaderInterface {
+
+  /**
+   * Includes a PHP file.
+   *
+   * @param string $filename
+   *   The filename. Can be a relative path.
+   *
+   * @return bool
+   *   TRUE if the include succeeded, FALSE if it failed.
+   */
+  public function includePhp($filename);
+
+  /**
+   * Writes a PHP file.
+   *
+   * @param string $filename
+   *   The filename. Can be a relative path.
+   * @param string $data
+   *    The PHP code to be written.
+   *
+   * @return bool
+   *   TRUE if the write succeeded, FALSE if it failed.
+   */
+  public function write($filename, $data);
+
+  /**
+   * Deletes a PHP file.
+   *
+   * @param string $filename
+   *   The filename to be deleted. Can be a relative path.
+   * @param string $bin
+   *   An optional bin. Separate bins can use a different loader class.
+   *
+   * @return bool
+   *   TRUE if the delete succeeded, FALSE if it failed.
+   */
+  public function delete($filename);
+}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index cccd011..5595a60 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -761,7 +761,7 @@ abstract class TestBase {
     }
 
     // Delete temporary files directory.
-    file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
+    _simpletest_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
 
     // Restore original database connection.
     Database::removeConnection('default');
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 4138916..88ac724 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -507,7 +507,7 @@ function simpletest_clean_temporary_directories() {
     foreach ($files as $file) {
       $path = 'public://simpletest/' . $file;
       if (is_dir($path) && (is_numeric($file) || strpos($file, 'config_simpletest') !== FALSE)) {
-        file_unmanaged_delete_recursive($path);
+        _simpletest_delete_recursive($path);
         $count++;
       }
     }
@@ -522,6 +522,19 @@ function simpletest_clean_temporary_directories() {
 }
 
 /**
+ * Deletes a directory recursively regardless of permissions (if possible).
+ *
+ * @param $path
+ *   The path that will be obliterated.
+ */
+function _simpletest_delete_recursive($path) {
+  // file_unmanaged_delete_recursive()  deliberately only removes visible
+  // files with write permission.
+  chmod($path, 0700);
+  file_unmanaged_delete_recursive($path, '_simpletest_delete_recursive');
+}
+
+/**
  * Clear the test result tables.
  *
  * @param $test_id
diff --git a/core/modules/system/lib/Drupal/system/Tests/PhpLoader/MTimeProtectedLoaderTest.php b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/MTimeProtectedLoaderTest.php
new file mode 100644
index 0000000..ae0d549
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/MTimeProtectedLoaderTest.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\PhpLoader\MTimeProtectedLoaderTest
+ */
+
+namespace Drupal\system\Tests\PhpLoader;
+
+/**
+ * Tests the directory mtime based PHP loader implementation.
+ */
+class MTimeProtectedLoaderTest extends PhpLoaderTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'MTime loader',
+      'description' => 'Tests the protected loader.',
+      'group' => 'System',
+    );
+  }
+
+  /**
+   * Tests the directory mtime based PHP loader implementation.
+   *
+   * This test first writes a file containing the definition of a non-existing
+   * function returning a random. Then loads it back, calls the function and
+   * asserts the return is correct.
+   */
+  public function testMTimeProtectedLoader() {
+    $this->doTest(array('default' =>
+      array(
+        'class' => 'Drupal\Component\PhpLoader\MTimeProtectedLoader',
+        'prefix' => variable_get('file_public_path', conf_path() . '/files') . '/codegen',
+        'secret' => $GLOBALS['drupal_hash_salt'],
+      ),
+    ));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/PhpLoader/NativeLoaderTest.php b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/NativeLoaderTest.php
new file mode 100644
index 0000000..e478e8d
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/NativeLoaderTest.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\PhpLoader\MTimeProtectedLoaderTest
+ */
+
+namespace Drupal\system\Tests\PhpLoader;
+
+/**
+ * Tests the native loader.
+ */
+class NativeLoaderTest extends PhpLoaderTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Native loader',
+      'description' => 'Tests the native loader.',
+      'group' => 'System',
+    );
+  }
+
+  /**
+   * Tests the directory mtime based PHP loader implementation.
+   *
+   * This test first writes a file containing the definition of a non-existing
+   * function returning a random. Then loads it back, calls the function and
+   * asserts the return is correct.
+   */
+  public function testNativeLoader() {
+    $this->doTest(array('default' =>
+      array(
+        'class' => 'Drupal\Component\PhpLoader\NativeLoader',
+        'prefix' => variable_get('file_public_path', conf_path() . '/files') . '/codegen',
+      ),
+    ));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/PhpLoader/PhpLoaderTestBase.php b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/PhpLoaderTestBase.php
new file mode 100644
index 0000000..2f07937
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/PhpLoader/PhpLoaderTestBase.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\PhpLoader\PhpLoaderTestBase.
+ */
+
+namespace Drupal\system\Tests\PhpLoader;
+
+use Drupal\simpletest\UnitTestBase;
+
+/**
+ * Base test for PHP loaders.
+ */
+abstract class PhpLoaderTestBase extends UnitTestBase {
+
+  /**
+   * Test a loader.
+   *
+   * @param array $loader
+   *   A loader configuration array as used for the loader_classes variable in
+   *   drupal_php_loader().
+   */
+  public function doTest($loader) {
+    $conf['loader_classes'] = $loader;
+    drupal_static_reset('_drupal_php_get_loader');
+    $filename = $this->randomName() . '/' . $this->randomName() . '.php';
+    do {
+      $random = mt_rand(10000, 100000);
+      $function = 'test' . $random;
+    } while (function_exists($function));
+    $contents = "<?php\nfunction $function() { return $random;}";
+    drupal_php_loader()->write($filename, $contents);
+    drupal_php_loader()->includePhp($filename);
+    $this->assertIdentical($function(), $random);
+  }
+}
