diff --git a/modules/user/user.module b/modules/user/user.module
index 4492c60..e198efb 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2724,35 +2724,36 @@ function user_mail_tokens(&$replacements, $data, $options) {
  *   value.
  */
 function user_roles($membersonly = FALSE, $permission = NULL) {
-  $query = db_select('role', 'r');
-  $query->addTag('translatable');
-  $query->fields('r', array('rid', 'name'));
-  $query->orderBy('weight');
-  $query->orderBy('name');
-  if (!empty($permission)) {
-    $query->innerJoin('role_permission', 'p', 'r.rid = p.rid');
-    $query->condition('p.permission', $permission);
-  }
-  $result = $query->execute();
-
-  $roles = array();
-  foreach ($result as $role) {
-    switch ($role->rid) {
-      // We only translate the built in role names
-      case DRUPAL_ANONYMOUS_RID:
-        if (!$membersonly) {
+  if (empty($permission)) {
+    $roles = drupal_static(__FUNCTION__);
+  }
+  if (empty($roles)) {
+    $query = db_select('role', 'r');
+    $query->addTag('translatable');
+    $query->fields('r', array('rid', 'name'));
+    $query->orderBy('weight');
+    $query->orderBy('name');
+    if (!empty($permission)) {
+      $query->innerJoin('role_permission', 'p', 'r.rid = p.rid');
+      $query->condition('p.permission', $permission);
+    }
+    $result = $query->execute();
+  
+    $roles = array();
+    foreach ($result as $role) {
+      switch ($role->rid) {
+        // We only translate the built in role names
+        case DRUPAL_ANONYMOUS_RID:
+        case DRUPAL_AUTHENTICATED_RID:
           $roles[$role->rid] = t($role->name);
-        }
-        break;
-      case DRUPAL_AUTHENTICATED_RID:
-        $roles[$role->rid] = t($role->name);
-        break;
-      default:
-        $roles[$role->rid] = $role->name;
+          break;
+        default:
+          $roles[$role->rid] = $role->name;
+      }
     }
   }
 
-  return $roles;
+  return $membersonly ? array_diff_key($roles, array(DRUPAL_ANONYMOUS_RID => NULL)) : $roles;
 }
 
 /**
