diff --git a/core/lib/Drupal/Component/PhpLoader/NativeLoader.php b/core/lib/Drupal/Component/PhpLoader/NativeLoader.php
new file mode 100644
index 0000000..7355a2d
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/NativeLoader.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Component\PhpLoader;
+
+class NativeLoader implements PhpLoaderInterface {
+  protected $prefix;
+  function __construct($config) {
+    $this->prefix = $config['prefix'];
+  }
+  function read($filename) {
+    include_once $this->prefix . '/' . $filename;
+  }
+  function write($filename, $data) {
+    return file_put_contents($this->prefix . '/' . $filename, $data);
+  }
+  function delete($filename) {
+    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..a2acf96
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/PhpLoaderInterface.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Drupal\Component\PhpLoader;
+
+interface PhpLoaderInterface {
+  function read($filename);
+
+  function write($filename, $data);
+
+  function delete($filename);
+}
diff --git a/core/lib/Drupal/Component/PhpLoader/ProtectedLoader.php b/core/lib/Drupal/Component/PhpLoader/ProtectedLoader.php
new file mode 100644
index 0000000..b2a0897
--- /dev/null
+++ b/core/lib/Drupal/Component/PhpLoader/ProtectedLoader.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace Drupal\Component\PhpLoader;
+
+class ProtectedLoader implements PhpLoaderInterface {
+  protected $prefix;
+  protected $mtime = 0;
+
+  /**
+   * var $hmac Callable
+   */
+  protected $hmac;
+
+  function __construct($config) {
+    $this->prefix = $config['prefix'];
+    $this->salt = $config['salt'];
+    $this->hmac = $config['hmac'];
+  }
+
+  function read($filename) {
+    $filename = str_replace('/', '#', $filename);
+    $dir = $this->prefix . '/' . $filename;
+    if (file_exists($dir)) {
+      $dir_mtime = filemtime($dir);
+      $filename = $dir . '/' . call_user_func($this->hmac, $filename, $this->salt . $dir_mtime);
+      // First, we know that if any file has been created or deleted in the
+      // directory then the directory mtime changes and so it invalidates the
+      // hash. Therefore, if the filename exists then the directory mtime is
+      // still the same as it was in drupal_php_write(). As
+      // _drupal_php_write_sleep() sleeps until the current time is larger than
+      // that, if another process would write the file then it would make the
+      // file mtime strictly larger than the directory mtime.
+      if (file_exists($filename) && filemtime($filename) <= $dir_mtime) {
+        include_once $filename;
+      }
+    }
+  }
+
+  function write($filename, $data) {
+    $filename = str_replace('/', '#', $filename);
+    $original_path = "$this->prefix/.$filename";
+    if (!@file_put_contents($original_path, $data)) {
+      return FALSE;
+    }
+    chmod($original_path, 0400);
+    $full_dir = $this->prefix . '/' . $filename;
+    if (file_exists($full_dir)) {
+      // Garbage collection.
+      foreach (new DirectoryIterator($full_dir) as $entry) {
+        if ($entry->isFile()) {
+          unlink($entry->isFile());
+        }
+      }
+      touch($full_dir);
+    }
+    else {
+      mkdir($full_dir);
+    }
+    $this->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. So renaming needs
+    // to happen in a loop. Also note that clearstatcache() returns NULL so it
+    // does not affect the loop condition.
+    while (clearstatcache() || $this->mtime != filemtime($full_dir)) {
+      // Reset the file back in the original place if this is not the first
+      // iteration.
+      if ($loop) {
+        rename($full_path, $original_path);
+      }
+      if ($loop > 10) {
+        // Hopelessly slow filesystem?
+        unlink($original_path);
+        return FALSE;
+      }
+      $full_path = $full_dir . '/' . call_user_func($this->hmac, $filename, $this->salt . $dir_mtime);
+      rename($original_path, $full_path);
+      $loop++;
+    }
+  }
+
+  function delete($filename) {
+    $filename = str_replace('/', '#', $filename);
+    $dir = $this->prefix . '/' . $filename;
+    $iterator = new RecursiveIteratorIterator(
+      new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
+      RecursiveIteratorIterator::CHILD_FIRST
+    );
+    foreach ($iterator as $file) {
+      if ($file->isDir()) {
+        rmdir($file->getPathname());
+      }
+      else {
+        unlink($file->getPathname());
+      }
+    }
+    rmdir($dir);
+  }
+
+  function __destruct() {
+    $time = $this->mtime + 1;
+    // time_sleep_until() throws a warning if the time given is in the past.
+    if (time() < $time) {
+      time_sleep_until($time);
+    }
+  }
+}
