diff --git a/core/modules/views/src/ViewsData.php b/core/modules/views/src/ViewsData.php
index bd65aa8..0fbe5fc 100644
--- a/core/modules/views/src/ViewsData.php
+++ b/core/modules/views/src/ViewsData.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
@@ -230,7 +231,19 @@ protected function getData() {
       return $data->data;
     }
     else {
-      $data = $this->moduleHandler->invokeAll('views_data');
+      $modules = $this->moduleHandler->getImplementations('views_data');
+      $data = array();
+      foreach ($modules as $module) {
+        $views_data = $this->moduleHandler->invoke($module, 'views_data');
+
+        // Set the provider key for each base table.
+        foreach ($views_data as &$table) {
+          if (isset($table['table']) && !isset($table['table']['provider'])) {
+            $table['table']['provider'] = $module;
+          }
+        }
+        $data = NestedArray::mergeDeep($data, $views_data);
+      }
       $this->moduleHandler->alter('views_data', $data);
 
       $this->processEntityTypes($data);
diff --git a/core/modules/views/tests/src/ViewsDataTest.php b/core/modules/views/tests/src/ViewsDataTest.php
index d06cd06..a2e7d4d 100644
--- a/core/modules/views/tests/src/ViewsDataTest.php
+++ b/core/modules/views/tests/src/ViewsDataTest.php
@@ -108,20 +108,51 @@ protected function viewsData() {
   }
 
   /**
-   * Tests the fetchBaseTables() method.
+   * Returns the views data definition with the provider key.
+   *
+   * @return array
+   *
+   * @see static::viewsData()
    */
-  public function testFetchBaseTables() {
-    $views_data = $this->viewsData();
+  protected function viewsDataWithProvider() {
+    $views_data = static::viewsData();
+    foreach (array_keys($views_data) as $table) {
+      $views_data[$table]['table']['provider'] = 'views_test_data';
+    }
+    return $views_data;
+  }
 
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
+  /**
+   * Mocks the basic module handler used for the test.
+   *
+   * @return \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected function setupMockedModuleHandler() {
+    $views_data = $this->viewsData();
+    $this->moduleHandler->expects($this->at(0))
+      ->method('getImplementations')
       ->with('views_data')
-      ->will($this->returnValue($views_data));
+      ->willReturn(array('views_test_data'));
+    $this->moduleHandler->expects($this->at(1))
+      ->method('invoke')
+      ->with('views_test_data', 'views_data')
+      ->willReturn($views_data);
+  }
 
+  /**
+   * Tests the fetchBaseTables() method.
+   */
+  public function testFetchBaseTables() {
+    $this->setupMockedModuleHandler();
     $data = $this->viewsData->get();
 
     $base_tables = $this->viewsData->fetchBaseTables();
 
+    // Ensure that 'provider' is set for each base table.
+    foreach (array_keys($base_tables) as $base_table) {
+      $this->assertEquals('views_test_data', $data[$base_table]['table']['provider']);
+    }
+
     // Test the number of tables returned and their order.
     $this->assertCount(6, $base_tables, 'The correct amount of base tables were returned.');
     $base_tables_keys = array_keys($base_tables);
@@ -150,24 +181,19 @@ public function testFetchBaseTables() {
    * Tests fetching all the views data without a static cache.
    */
   public function testGetOnFirstCall() {
-    $views_data = $this->viewsData();
-
     // Ensure that the hooks are just invoked once.
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
-      ->with('views_data')
-      ->will($this->returnValue($views_data));
+    $this->setupMockedModuleHandler();
 
-    $this->moduleHandler->expects($this->once())
+    $this->moduleHandler->expects($this->at(2))
       ->method('alter')
-      ->with('views_data', $views_data);
+      ->with('views_data', $this->viewsDataWithProvider());
 
     $this->cacheBackend->expects($this->once())
       ->method('get')
       ->with("views_data:en")
       ->will($this->returnValue(FALSE));
 
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $views_data = $this->viewsData->get();
     $this->assertSame($expected_views_data, $views_data);
   }
@@ -176,21 +202,37 @@ public function testGetOnFirstCall() {
    * Tests the cache of the full and single table data.
    */
   public function testFullAndTableGetCache() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $table_name = 'views_test_data';
     $table_name_2 = 'views_test_data_2';
     $random_table_name = $this->randomMachineName();
 
     // Views data should be invoked twice due to the clear call.
-    $this->moduleHandler->expects($this->exactly(2))
-      ->method('invokeAll')
+    $this->moduleHandler->expects($this->at(0))
+      ->method('getImplementations')
       ->with('views_data')
-      ->will($this->returnValue($expected_views_data));
+      ->willReturn(array('views_test_data'));
+    $this->moduleHandler->expects($this->at(1))
+      ->method('invoke')
+      ->with('views_test_data', 'views_data')
+      ->willReturn($this->viewsData());
+    $this->moduleHandler->expects($this->at(2))
+      ->method('alter')
+      ->with('views_data', $expected_views_data);
 
-    $this->moduleHandler->expects($this->exactly(2))
+    $this->moduleHandler->expects($this->at(3))
+      ->method('getImplementations')
+      ->with('views_data')
+      ->willReturn(array('views_test_data'));
+    $this->moduleHandler->expects($this->at(4))
+      ->method('invoke')
+      ->with('views_test_data', 'views_data')
+      ->willReturn($this->viewsData());
+    $this->moduleHandler->expects($this->at(5))
       ->method('alter')
       ->with('views_data', $expected_views_data);
 
+
     // The cache should only be called once (before the clear() call) as get
     // will get all table data in the first get().
     $this->cacheBackend->expects($this->at(0))
@@ -251,13 +293,10 @@ public function testFullAndTableGetCache() {
    * Tests the caching of the full views data.
    */
   public function testFullGetCache() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
 
     // Views data should be invoked once.
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
-      ->with('views_data')
-      ->will($this->returnValue($expected_views_data));
+    $this->setupMockedModuleHandler();
 
     $this->moduleHandler->expects($this->once())
       ->method('alter')
@@ -280,17 +319,14 @@ public function testFullGetCache() {
    */
   public function testSingleTableGetCache() {
     $table_name = 'views_test_data';
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
 
     // Views data should be invoked once.
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
-      ->with('views_data')
-      ->will($this->returnValue($expected_views_data));
+    $this->setupMockedModuleHandler();
 
     $this->moduleHandler->expects($this->once())
       ->method('alter')
-      ->with('views_data', $expected_views_data);
+      ->with('views_data', $this->viewsDataWithProvider());
 
     $this->cacheBackend->expects($this->at(0))
       ->method('get')
@@ -319,17 +355,13 @@ public function testSingleTableGetCache() {
    */
   public function testNonExistingTableGetCache() {
     $random_table_name = $this->randomMachineName();
-    $expected_views_data = $this->viewsData();
 
     // Views data should be invoked once.
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
-      ->with('views_data')
-      ->will($this->returnValue($expected_views_data));
+    $this->setupMockedModuleHandler();
 
     $this->moduleHandler->expects($this->once())
       ->method('alter')
-      ->with('views_data', $expected_views_data);
+      ->with('views_data', $this->viewsDataWithProvider());
 
     $this->cacheBackend->expects($this->at(0))
       ->method('get')
@@ -353,12 +385,9 @@ public function testNonExistingTableGetCache() {
    * Tests the cache backend behavior with requesting the same table multiple
    */
   public function testCacheCallsWithSameTableMultipleTimes() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
 
-    $this->moduleHandler->expects($this->any())
-      ->method('invokeAll')
-      ->with('views_data')
-      ->will($this->returnValue($expected_views_data));
+    $this->setupMockedModuleHandler();
 
     $this->cacheBackend->expects($this->at(0))
       ->method('get')
@@ -391,9 +420,9 @@ public function testCacheCallsWithSameTableMultipleTimes() {
    *   - views_test_data
    */
   public function testCacheCallsWithSameTableMultipleTimesAndWarmCache() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $this->moduleHandler->expects($this->never())
-      ->method('invokeAll');
+      ->method('getImplementations');
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->once())
@@ -421,9 +450,9 @@ public function testCacheCallsWithSameTableMultipleTimesAndWarmCache() {
    *   - views_test_data_2
    */
   public function testCacheCallsWithWarmCacheAndDifferentTable() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $this->moduleHandler->expects($this->never())
-      ->method('invokeAll');
+      ->method('getImplementations');
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->at(0))
@@ -456,10 +485,10 @@ public function testCacheCallsWithWarmCacheAndDifferentTable() {
    *   - $non_existing_table
    */
   public function testCacheCallsWithWarmCacheAndInvalidTable() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $non_existing_table = $this->randomMachineName();
     $this->moduleHandler->expects($this->never())
-      ->method('invokeAll');
+      ->method('getImplementations');
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->at(0))
@@ -495,7 +524,7 @@ public function testCacheCallsWithWarmCacheAndInvalidTable() {
   public function testCacheCallsWithWarmCacheForInvalidTable() {
     $non_existing_table = $this->randomMachineName();
     $this->moduleHandler->expects($this->never())
-      ->method('invokeAll');
+      ->method('getImplementations');
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->once())
@@ -520,10 +549,8 @@ public function testCacheCallsWithWarmCacheForInvalidTable() {
    * Tests the cache calls for all views data without a warm cache.
    */
   public function testCacheCallsWithoutWarmCacheAndGetAllTables() {
-    $expected_views_data = $this->viewsData();
-    $this->moduleHandler->expects($this->once())
-      ->method('invokeAll')
-      ->will($this->returnValue($expected_views_data));
+    $expected_views_data = $this->viewsDataWithProvider();
+    $this->setupMockedModuleHandler();
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->once())
@@ -548,9 +575,9 @@ public function testCacheCallsWithoutWarmCacheAndGetAllTables() {
    *   - all tables
    */
   public function testCacheCallsWithWarmCacheAndGetAllTables() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $this->moduleHandler->expects($this->never())
-      ->method('invokeAll');
+      ->method('getImplementations');
 
     // Setup a warm cache backend for a single table.
     $this->cacheBackend->expects($this->once())
@@ -574,7 +601,7 @@ public function testCacheCallsWithWarmCacheAndGetAllTables() {
    * @covers ::get
    */
   public function testCacheCallsWithoutWarmCacheAndGetMultipleTables() {
-    $expected_views_data = $this->viewsData();
+    $expected_views_data = $this->viewsDataWithProvider();
     $table_name = 'views_test_data';
     $table_name_2 = 'views_test_data_2';
 
