diff --git modules/taxonomy/taxonomy.admin.inc modules/taxonomy/taxonomy.admin.inc
index 62b1c66..bdf28a4 100644
--- modules/taxonomy/taxonomy.admin.inc
+++ modules/taxonomy/taxonomy.admin.inc
@@ -675,28 +675,45 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary =
   // full vocabulary. Contrib modules can then intercept before
   // hook_form_alter to provide scalable alternatives.
   if (!variable_get('taxonomy_override_selector', FALSE)) {
-    $parent = array_keys(taxonomy_get_parents($edit['tid']));
-    $children = taxonomy_get_tree($vocabulary->vid, $edit['tid']);
+    $thresholds = variable_get('taxonomy_vocabulary_term_counts', array());
 
-    // A term can't be the child of itself, nor of its children.
-    foreach ($children as $child) {
-      $exclude[] = $child->tid;
-    }
-    $exclude[] = $edit['tid'];
+    if (empty($thresholds[$vocabulary->machine_name])) {
+      $parent = array_keys(taxonomy_get_parents($edit['tid']));
+      $children = taxonomy_get_tree($vocabulary->vid, $edit['tid']);
+
+      // A term can't be the child of itself, nor of its children.
+      foreach ($children as $child) {
+        $exclude[] = $child->tid;
+      }
+      $exclude[] = $edit['tid'];
 
-    $tree = taxonomy_get_tree($vocabulary->vid);
-    $options = array('<' . t('root') . '>');
-    foreach ($tree as $term) {
-      if (!in_array($term->tid, $exclude)) {
-        $options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
+      $tree = taxonomy_get_tree($vocabulary->vid);
+      $options = array('<' . t('root') . '>');
+      foreach ($tree as $term) {
+        if (!in_array($term->tid, $exclude)) {
+          $options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
+        }
       }
+      $form['relations']['parent'] = array(
+        '#type' => 'select',
+        '#options' => $options,
+        '#default_value' => $parent,
+        '#multiple' => TRUE,
+      );
+    }
+    else {
+      $parent = taxonomy_get_parents($edit['tid']);
+      $typed_string = taxonomy_implode_tags($parent, $vocabulary->vid);
+
+      $form['relations']['parent'] = array(
+        '#type' => 'textfield',
+        '#autocomplete_path' => 'taxonomy/autocomplete/parent/' . $vocabulary->vid,
+        '#default_value' => $typed_string,
+        '#element_validate' => array('taxonomy_autocomplete_parent_validate'),
+      );
     }
-    $form['relations']['parent'] = array(
-      '#type' => 'select',
+    $form['relations']['parent'] += array(
       '#title' => t('Parent terms'),
-      '#options' => $options,
-      '#default_value' => $parent,
-      '#multiple' => TRUE,
     );
 
   }
diff --git modules/taxonomy/taxonomy.module modules/taxonomy/taxonomy.module
index 42a8f62..5ed91df 100644
--- modules/taxonomy/taxonomy.module
+++ modules/taxonomy/taxonomy.module
@@ -301,6 +301,13 @@ function taxonomy_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'taxonomy.pages.inc',
   );
+  $items['taxonomy/autocomplete/parent'] = array(
+    'title' => 'Autocomplete taxonomy',
+    'page callback' => 'taxonomy_autocomplete_legacy',
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+    'file' => 'taxonomy.pages.inc',
+  );
 
   $items['admin/structure/taxonomy/%taxonomy_vocabulary'] = array(
     'title callback' => 'taxonomy_admin_vocabulary_title_callback',
@@ -1364,6 +1371,45 @@ function taxonomy_autocomplete_validate($element, &$form_state) {
 }
 
 /**
+ * Form element validate handler for taxonomy term autocomplete element.
+ */
+function taxonomy_autocomplete_parent_validate($element, &$form_state) {
+  // Autocomplete widgets do not send their tids in the form, so we must detect
+  // them here and process them independently.
+  if ($tags = $element['#value']) {
+    // Collect candidate vocabularies.
+    $vid = $form_state['values']['vid'];
+
+    // Translate term names into actual terms.
+    $typed_terms = drupal_explode_tags($tags);
+    $values = array();
+    foreach ($typed_terms as $typed_term) {
+      // See if the term exists in the chosen vocabulary and return the tid;
+      // otherwise, create a new term.
+      if ($possibilities = taxonomy_term_load_multiple(array(), array('name' => trim($typed_term), 'vid' => $vid))) {
+        $term = array_pop($possibilities);
+      }
+      else {
+        $vocabulary = taxonomy_vocabulary_load($vid);
+        $term = (object) array(
+          'vid' => $vid,
+          'name' => $typed_term,
+          'vocabulary_machine_name' => $vocabulary->machine_name,
+        );
+        taxonomy_term_save($term);
+      }
+      $values[] = $term->tid;
+    }
+    $value = options_array_transpose(array('tid' => $values));
+  }
+  else {
+    $value = array();
+  }
+
+  form_set_value($element, $value, $form_state);
+}
+
+/**
  * Implements hook_field_widget_error().
  */
 function taxonomy_field_widget_error($element, $error, $form, &$form_state) {
@@ -1540,3 +1586,27 @@ function taxonomy_taxonomy_term_delete($term) {
 /**
  * @} End of "defgroup taxonomy indexing"
  */
+
+/**
+ * Implements hook_taxonomy_term_insert().
+ *
+ * For large vocabularies or taxonomy term reference fields with many allowed
+ * values, Drupal core options widgets become unusable.
+ */
+function taxonomy_taxonomy_term_insert($term) {
+  $counts = variable_get('taxonomy_vocabulary_term_counts', array());
+
+  // Counts array stores vocabulary machine name when the vocabulary has
+  // exceeded the autocomplete threshold.
+  if (empty($counts[$term->vocabulary_machine_name])) {
+    $count = db_select('taxonomy_term_data', 't')
+      ->condition('t.vid', $term->vid)
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+    if ($count > variable_get('taxonomy_autocomplete_threshold', 150)) {
+      $counts[$term->vocabulary_machine_name] = $term->vocabulary_machine_name;
+      variable_set('taxonomy_vocabulary_term_counts', $counts);
+    }
+  }
+}
diff --git modules/taxonomy/taxonomy.pages.inc modules/taxonomy/taxonomy.pages.inc
index dd6e8a0..0305e1c 100644
--- modules/taxonomy/taxonomy.pages.inc
+++ modules/taxonomy/taxonomy.pages.inc
@@ -123,3 +123,49 @@ function taxonomy_autocomplete($field_name, $tags_typed = '') {
 
   drupal_json_output($term_matches);
 }
+
+/**
+ * Helper function for autocompletion
+ */
+function taxonomy_autocomplete_legacy($vid = 0, $tags_typed = '') {
+  // The user enters a comma-separated list of tags. We only autocomplete the last tag.
+  $tags_typed = drupal_explode_tags($tags_typed);
+  $tag_last = drupal_strtolower(array_pop($tags_typed));
+
+  $matches = array();
+  if ($tag_last != '') {
+
+    $query = db_select('taxonomy_term_data', 't');
+    $query->addTag('translatable');
+    $query->addTag('term_access');
+
+    // Do not select already entered terms.
+    if (!empty($tags_typed)) {
+      $query->condition('t.name', $tags_typed, 'NOT IN');
+    }
+    // Select rows that match by term name.
+    $tags_return = $query
+      ->fields('t', array('tid', 'name'))
+      ->condition('t.vid', $vid)
+      ->condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')
+      ->range(0, 10)
+      ->execute()
+      ->fetchAllKeyed();
+
+    $prefix = count($tags_typed) ? implode(', ', $tags_typed) . ', ' : '';
+
+    $term_matches = array();
+    foreach ($tags_return as $tid => $name) {
+      $n = $name;
+      // Term names containing commas or quotes must be wrapped in quotes.
+      if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
+        $n = '"' . str_replace('"', '""', $name) . '"';
+      }
+      else {
+        $term_matches[$prefix . $n] = check_plain($name);
+      }
+    }
+  }
+
+  drupal_json_output($term_matches);
+}
