Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 15775)
+++ wp-includes/post.php	(working copy)
@@ -366,6 +366,11 @@
 	} elseif ( is_object($post) && empty($post->filter) ) {
 		_get_post_ancestors($post);
 		$_post = sanitize_post($post, 'raw');
+		if ( $cached_post = wp_cache_get($_post->ID, 'posts') ) {
+			if ( ! isset($cached_post->ancestors) )
+				wp_cache_delete($_post->ID, 'posts');
+		}
+		unset($cached_post);
 		wp_cache_add($post->ID, $_post, 'posts');
 	} else {
 		if ( is_object($post) )
@@ -381,10 +386,13 @@
 			_get_post_ancestors($_post);
 			$_post = sanitize_post($_post, 'raw');
 			wp_cache_add($_post->ID, $_post, 'posts');
+		} elseif ( ! isset($_post->ancestors) ) {
+			_get_post_ancestors($_post);
+			wp_cache_set($_post->ID, $_post, 'posts');
 		}
 	}
 
-	if ($filter != 'raw')
+	if ( $filter != 'raw' )
 		$_post = sanitize_post($_post, $filter);
 
 	if ( $output == OBJECT ) {
@@ -2265,15 +2273,23 @@
 	else
 		$post_parent = 0;
 
+	// Ancestor circular dependency detection
 	if ( !empty($post_ID) ) {
 		if ( $post_parent == $post_ID ) {
 			// Post can't be its own parent
 			$post_parent = 0;
 		} elseif ( !empty($post_parent) ) {
-			$parent_post = get_post($post_parent);
-			// Check for circular dependency
-			if ( isset( $parent_post->post_parent ) && $parent_post->post_parent == $post_ID )
-				$post_parent = 0;
+			$parent_id = $post_parent;
+			$ancestors = array( $post_ID, $parent_id );
+			while ( $ancestor = $wpdb->get_var( $wpdb->prepare("SELECT `post_parent` FROM $wpdb->posts WHERE ID = %d LIMIT 1", $parent_id) ) ) {
+				// Loop detection: If the ancestor has been seen before, set parent to 0 and break.
+				if ( in_array($ancestor,  $ancestors) ) {
+					$post_parent = 0;
+					break;
+				}
+				$parent_id = $ancestors[] = $ancestor;
+			}
+			unset($ancestors);
 		}
 	}
 
@@ -3011,16 +3027,15 @@
  * @return string Page URI.
  */
 function get_page_uri($page) {
-	if ( ! is_object($page) )
-		$page = get_page($page);
+	$page = get_page($page);
 	$uri = $page->post_name;
 
 	// A page cannot be it's own parent.
-	if ( $page->post_parent == $page->ID )
+	if ( $page->post_parent == $page->ID || 0 == $page->post_parent )
 		return $uri;
 
-	while ($page->post_parent != 0) {
-		$page = get_page($page->post_parent);
+	foreach ( $page->ancestors as $ancestor) {
+		$page = get_page($ancestor);
 		$uri = $page->post_name . "/" . $uri;
 	}
 
@@ -4327,12 +4342,17 @@
 	if ( empty($_post->post_parent) || $_post->ID == $_post->post_parent )
 		return;
 
-	$id = $_post->ancestors[] = $_post->post_parent;
-	while ( $ancestor = $wpdb->get_var( $wpdb->prepare("SELECT `post_parent` FROM $wpdb->posts WHERE ID = %d LIMIT 1", $id) ) ) {
+	$ancestor = $_post->post_parent;
+	while ( $ancestor ) {
 		// Loop detection: If the ancestor has been seen before, break.
 		if ( ( $ancestor == $_post->ID ) || in_array($ancestor,  $_post->ancestors) )
 			break;
-		$id = $_post->ancestors[] = $ancestor;
+		$_post->ancestors[] = $ancestor;
+		if ( false === ( $ancestor = wp_cache_get($ancestor, 'posts') ) ) {
+			$ancestor = $wpdb->get_var( $wpdb->prepare("SELECT `post_parent` FROM $wpdb->posts WHERE ID = %d LIMIT 1", $ancestor) );
+		} else {
+			$ancestor = $ancestor->post_parent;
+		}
 	}
 }
 
Index: wp-admin/includes/default-list-tables.php
===================================================================
--- wp-admin/includes/default-list-tables.php	(revision 15775)
+++ wp-admin/includes/default-list-tables.php	(working copy)
@@ -333,7 +333,7 @@
 			$children_pages = array();
 
 			foreach ( $pages as $page ) {
-
+				$page = get_post($page);
 				// catch and repair bad pages
 				if ( $page->post_parent == $page->ID ) {
 					$page->post_parent = 0;
@@ -479,19 +479,12 @@
 
 					if ( 0 == $level && (int) $post->post_parent > 0 ) {
 						//sent level 0 by accident, by default, or because we don't know the actual level
-						$find_main_page = (int) $post->post_parent;
-						while ( $find_main_page > 0 ) {
-							$parent = get_page( $find_main_page );
+						$level = count($post->ancestors);
 
-							if ( is_null( $parent ) )
-								break;
+						$parent = get_page( $post->ancestors[$level] );
 
-							$level++;
-							$find_main_page = (int) $parent->post_parent;
-
-							if ( !isset( $parent_name ) )
-								$parent_name = $parent->post_title;
-						}
+						if ( !isset( $parent_name ) )
+							$parent_name = $parent->post_title;
 					}
 
 					$post->post_title = esc_html( $post->post_title );
