diff --git a/includes/module.inc b/includes/module.inc
index faf33eac972ce634f0a2be49530108a1949ce2cd..3e05d62a2cca274708b7af52b627c32a3ecd25d4 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -36,15 +36,19 @@ function module_iterate($function, $argument = '') {
  * @param $bootstrap
  *   Whether to return the reduced set of modules loaded in "bootstrap mode"
  *   for cached pages. See bootstrap.inc.
+ * @param $sort
+ *   By default, modules are ordered by weight and filename, settings this option
+ *   to TRUE, module list will be ordered by module name.
  * @return
  *   An associative array whose keys and values are the names of all loaded
  *   modules.
  */
-function module_list($refresh = FALSE, $bootstrap = TRUE) {
-  static $list;
+function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE) {
+  static $list, $sorted_list;
 
   if ($refresh) {
     $list = array();
+    $sorted_list = NULL;
   }
 
   if (!$list) {
@@ -68,6 +72,13 @@ function module_list($refresh = FALSE, $bootstrap = TRUE) {
       }
     }
   }
+  if ($sort) {
+    if (!isset($sorted_list)) {
+      $sorted_list = $list;
+      ksort($sorted_list);
+    }
+    return $sorted_list;
+  }
   return $list;
 }
 
@@ -125,15 +136,18 @@ function module_hook($module, $hook) {
  *
  * @param $hook
  *   The name of the hook (e.g. "help" or "menu").
+ * @param $sort
+ *   By default, modules are ordered by weight and filename, settings this option
+ *   to TRUE, module list will be ordered by module name.
  * @return
  *   An array with the names of the modules which are implementing this hook.
  */
-function module_implements($hook) {
+function module_implements($hook, $sort = FALSE) {
   static $implementations;
 
   if (!isset($implementations[$hook])) {
     $implementations[$hook] = array();
-    $list = module_list();
+    $list = module_list(FALSE, TRUE, $sort);
     foreach ($list as $module) {
       if (module_hook($module, $hook)) {
         $implementations[$hook][] = $module;
diff --git a/modules/user.module b/modules/user.module
index 57447b48cb61288d42464dcf0d7b89e69faa282f..be46ff8ca99797f002280aa258a427fe03d37fbd 100644
--- a/modules/user.module
+++ b/modules/user.module
@@ -1691,7 +1691,7 @@ function user_admin_perm($str_rids = NULL) {
 
   // Render role/permission overview:
   $options = array();
-  foreach (module_list() as $module) {
+  foreach (module_list(FALSE, FALSE, TRUE) as $module) {
     if ($permissions = module_invoke($module, 'perm')) {
       $form['permission'][] = array('#type' => 'markup', '#value' => t('%module module', array('%module' => $module)));
       asort($permissions);
diff --git a/modules/user/user.module b/modules/user/user.module
index 57447b48cb61288d42464dcf0d7b89e69faa282f..be46ff8ca99797f002280aa258a427fe03d37fbd 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -1691,7 +1691,7 @@ function user_admin_perm($str_rids = NULL) {
 
   // Render role/permission overview:
   $options = array();
-  foreach (module_list() as $module) {
+  foreach (module_list(FALSE, FALSE, TRUE) as $module) {
     if ($permissions = module_invoke($module, 'perm')) {
       $form['permission'][] = array('#type' => 'markup', '#value' => t('%module module', array('%module' => $module)));
       asort($permissions);