Index: src/wp-includes/class-wp-post-type.php
===================================================================
--- src/wp-includes/class-wp-post-type.php	(revision 38260)
+++ src/wp-includes/class-wp-post-type.php	(working copy)
@@ -325,7 +325,7 @@
 	public $rewrite;
 
 	/**
-	 * The features supported by the post type.
+	 * The features supported by the post type, per post type definition.
 	 *
 	 * @since 4.6.0
 	 * @access public
@@ -334,6 +334,15 @@
 	public $supports;
 
 	/**
+	 * All features supported by the post type.
+	 *
+	 * @since 4.7.0
+	 * @access private
+	 * @var array $features
+	 */
+	private $features = array();
+
+	/**
 	 * Constructor.
 	 *
 	 * Will populate object properties from the provided arguments and assign other
@@ -511,11 +520,11 @@
 	 */
 	public function add_supports() {
 		if ( ! empty( $this->supports ) ) {
-			add_post_type_support( $this->name, $this->supports );
+			$this->add_support( $this->supports );
 			unset( $this->supports );
 		} elseif ( false !== $this->supports ) {
 			// Add default features.
-			add_post_type_support( $this->name, array( 'title', 'editor' ) );
+			$this->add_support( array( 'title', 'editor' ) );
 		}
 	}
 
@@ -602,17 +611,123 @@
 	}
 
 	/**
+	 * Registers support of certain features for the post type.
+	 *
+	 * All core features are directly associated with a functional area of the edit
+	 * screen, such as the editor or a meta box. Features include: 'title', 'editor',
+	 * 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes',
+	 * 'thumbnail', 'custom-fields', and 'post-formats'.
+	 *
+	 * Additionally, the 'revisions' feature dictates whether the post type will
+	 * store revisions, and the 'comments' feature dictates whether the comments
+	 * count will show on the edit screen.
+	 *
+	 * @since 4.7.0
+	 * @access public
+	 *
+	 * @param string|array $feature The feature being added, accepts an array of
+	 *                              feature strings or a single string.
+	 * @param bool         $value   Optional. The value to give to the feature. Default
+	 *                              true.
+	 * @param string       $subtype Optional. A subtype to add this feature to. An
+	 *                              empty value will add this feature to the overall
+	 *                              post type. Default empty.
+	 */
+	public function add_support( $feature, $value = true, $subtype = '' ) {
+		$features = (array) $feature;
+		foreach ( $features as $feature ) {
+			$this->features[ $subtype ][ $feature ] = $value;
+		}
+	}
+
+	/**
+	 * Removes support for a feature from the post type.
+	 *
+	 * @since 4.7.0
+	 * @access public
+	 *
+	 * @param string $feature The feature being removed.
+	 * @param string $subtype Optional. A subtype to remove this feature from. An
+	 *                        empty value will remove this feature from the overall
+	 *                        post type. Default empty.
+	 */
+	public function remove_support( $feature, $subtype = '' ) {
+		unset( $this->features[ $subtype ][ $feature ] );
+	}
+
+	/**
+	 * Gets all the post type features.
+	 *
+	 * @since 4.7.0
+	 * @access public
+	 *
+	 * @param string $subtype Optional. A subtype to get its features. An
+	 *                        empty value will return the overall post type
+	 *                        features. Default empty.
+	 * @return array Post type supports list.
+	 */
+	public function get_all_supports( $subtype = '' ) {
+		return $this->features[ $subtype ];
+	}
+
+	/**
+	 * Checks the post type's support for a given feature.
+	 *
+	 * @since 4.7.0
+	 * @access public
+	 *
+	 * @param string $feature The feature being checked.
+	 * @param string $subtype Optional. A subtype to check in its features. An
+	 *                        empty value will check within the overall post type
+	 *                        features. Default empty.
+	 * @return bool Whether the post type supports the given feature.
+	 */
+	public function supports( $feature, $subtype = '' ) {
+		return isset( $this->features[ $subtype ][ $feature ] );
+	}
+
+	/**
+	 * Retrieves a list of post type and subtype names that support a specific feature.
+	 *
+	 * If the features are supported by the overall post type, the post type name is
+	 * included in the list. If the features are supported by a specific subtype, a
+	 * string consisting of post type name and subtype name delimited by a colon is
+	 * included in the list.
+	 *
+	 * @since 4.7.0
+	 * @access public
+	 *
+	 * @param array|string $feature  Single feature or an array of features the post type should support.
+	 * @param string       $operator Optional. The logical operation to perform. 'or' means
+	 *                               only one element from the array needs to match; 'and'
+	 *                               means all elements must match; 'not' means no elements may
+	 *                               match. Default 'and'.
+	 * @return array A list of post type and subtype names.
+	 */
+	public function get_by_support( $feature, $operator = 'and' ) {
+		$features = array_fill_keys( (array) $feature, true );
+		$subtypes = array_keys( wp_filter_object_list( $this->features, $features, $operator ) );
+
+		$names = array();
+		foreach ( $subtypes as $subtype ) {
+			if ( empty( $subtype ) ) {
+				$names[] = $this->name;
+			} else {
+				$names[] = $this->name . ':' . $subtype;
+			}
+		}
+
+		return $names;
+	}
+
+	/**
 	 * Removes the features support for the post type.
 	 *
 	 * @since 4.6.0
 	 * @access public
-	 *
-	 * @global array $_wp_post_type_features Post type features.
 	 */
 	public function remove_supports() {
-		global $_wp_post_type_features;
-
-		unset( $_wp_post_type_features[ $this->name ] );
+		$this->features = array();
 	}
 
 	/**
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 38260)
+++ src/wp-includes/post.php	(working copy)
@@ -1398,84 +1398,108 @@
  * count will show on the edit screen.
  *
  * @since 3.0.0
+ * @since 4.7.0 Uses `WP_Post_Type` to handle features.
  *
- * @global array $_wp_post_type_features
- *
  * @param string       $post_type The post type for which to add the feature.
  * @param string|array $feature   The feature being added, accepts an array of
  *                                feature strings or a single string.
  */
 function add_post_type_support( $post_type, $feature ) {
-	global $_wp_post_type_features;
+	$subtype = '';
+	if ( strpos( $post_type, ':' ) ) {
+		list( $post_type, $subtype ) = explode( ':', $post_type );
+	}
 
-	$features = (array) $feature;
-	foreach ($features as $feature) {
-		if ( func_num_args() == 2 )
-			$_wp_post_type_features[$post_type][$feature] = true;
-		else
-			$_wp_post_type_features[$post_type][$feature] = array_slice( func_get_args(), 2 );
+	$ptype_obj = get_post_type_object( $post_type );
+	if ( ! $ptype_obj ) {
+		return;
 	}
+
+	if ( func_num_args() == 2 ) {
+		$value = true;
+	} else {
+		$value = array_slice( func_get_args(), 2 );
+	}
+
+	$ptype_obj->add_support( $feature, $value, $subtype );
 }
 
 /**
  * Remove support for a feature from a post type.
  *
  * @since 3.0.0
+ * @since 4.7.0 Uses `WP_Post_Type` to handle features.
  *
- * @global array $_wp_post_type_features
- *
  * @param string $post_type The post type for which to remove the feature.
  * @param string $feature   The feature being removed.
  */
 function remove_post_type_support( $post_type, $feature ) {
-	global $_wp_post_type_features;
+	$subtype = '';
+	if ( strpos( $post_type, ':' ) ) {
+		list( $post_type, $subtype ) = explode( ':', $post_type );
+	}
 
-	unset( $_wp_post_type_features[ $post_type ][ $feature ] );
+	$ptype_obj = get_post_type_object( $post_type );
+	if ( ! $ptype_obj ) {
+		return;
+	}
+
+	$ptype_obj->remove_support( $feature, $subtype );
 }
 
 /**
  * Get all the post type features
  *
  * @since 3.4.0
+ * @since 4.7.0 Uses `WP_Post_Type` to handle features.
  *
- * @global array $_wp_post_type_features
- *
  * @param string $post_type The post type.
  * @return array Post type supports list.
  */
 function get_all_post_type_supports( $post_type ) {
-	global $_wp_post_type_features;
+	$subtype = '';
+	if ( strpos( $post_type, ':' ) ) {
+		list( $post_type, $subtype ) = explode( ':', $post_type );
+	}
 
-	if ( isset( $_wp_post_type_features[$post_type] ) )
-		return $_wp_post_type_features[$post_type];
+	$ptype_obj = get_post_type_object( $post_type );
+	if ( ! $ptype_obj ) {
+		return array();
+	}
 
-	return array();
+	return $ptype_obj->get_all_supports( $subtype );
 }
 
 /**
  * Check a post type's support for a given feature.
  *
  * @since 3.0.0
+ * @since 4.7.0 Uses `WP_Post_Type` to handle features.
  *
- * @global array $_wp_post_type_features
- *
  * @param string $post_type The post type being checked.
  * @param string $feature   The feature being checked.
  * @return bool Whether the post type supports the given feature.
  */
 function post_type_supports( $post_type, $feature ) {
-	global $_wp_post_type_features;
+	$subtype = '';
+	if ( strpos( $post_type, ':' ) ) {
+		list( $post_type, $subtype ) = explode( ':', $post_type );
+	}
 
-	return ( isset( $_wp_post_type_features[$post_type][$feature] ) );
+	$ptype_obj = get_post_type_object( $post_type );
+	if ( ! $ptype_obj ) {
+		return false;
+	}
+
+	return $ptype_obj->supports( $feature, $subtype );
 }
 
 /**
  * Retrieves a list of post type names that support a specific feature.
  *
  * @since 4.5.0
+ * @since 4.7.0 Uses `WP_Post_Type` to handle features.
  *
- * @global array $_wp_post_type_features Post type features
- *
  * @param array|string $feature  Single feature or an array of features the post types should support.
  * @param string       $operator Optional. The logical operation to perform. 'or' means
  *                               only one element from the array needs to match; 'and'
@@ -1484,11 +1508,14 @@
  * @return array A list of post type names.
  */
 function get_post_types_by_support( $feature, $operator = 'and' ) {
-	global $_wp_post_type_features;
+	$names = array();
 
-	$features = array_fill_keys( (array) $feature, true );
+	$ptype_objects = get_post_types( array(), 'objects' );
+	foreach ( $ptype_objects as $ptype_obj ) {
+		$names = array_merge( $names, $ptype_obj->get_by_support( $feature, $operator ) );
+	}
 
-	return array_keys( wp_filter_object_list( $_wp_post_type_features, $features, $operator ) );
+	return $names;
 }
 
 /**
