diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 3f5520a..9bef394 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -187,8 +187,14 @@ function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $opti
   foreach ($instances as $instance) {
     $field_name = $instance['field_name'];
     $field = field_info_field($field_name);
-    $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
-    if (function_exists($function)) {
+    $function = FALSE;
+    if ($options['default']) {
+      $function = 'field_default_' . $op;
+    }
+    elseif (module_hook($field['module'], 'field_' . $op)) {
+      $function = $field['module'] . '_field_' . $op;
+    }
+    if ($function) {
       // Determine the list of languages to iterate on.
       $available_languages = field_available_languages($entity_type, $field);
       $languages = _field_language_suggestion($available_languages, $options['language'], $field_name);
@@ -297,8 +303,14 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
       $field_id = $instance['field_id'];
       $field_name = $instance['field_name'];
       $field = $field_info[$field_id];
-      $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
-      if (function_exists($function)) {
+      $function = FALSE;
+      if ($options['default']) {
+        $function = 'field_default_' . $op;
+      }
+      elseif (module_hook($field['module'], 'field_' . $op)) {
+        $function = $field['module'] . '_field_' . $op;
+      }
+      if ($function) {
         // Add the field to the list of fields to invoke the hook on.
         if (!isset($fields[$field_id])) {
           $fields[$field_id] = $field;
@@ -326,7 +338,13 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
   // For each field, invoke the field hook and collect results.
   foreach ($fields as $field_id => $field) {
     $field_name = $field['field_name'];
-    $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+    $function = FALSE;
+    if ($options['default']) {
+      $function = 'field_default_' . $op;
+    }
+    elseif (module_hook($field['module'], 'field_' . $op)) {
+      $function = $field['module'] . '_field_' . $op;
+    }
     // Iterate over all the field translations.
     foreach ($grouped_items[$field_id] as $langcode => &$items) {
       $entities = $grouped_entities[$field_id][$langcode];
diff --git a/core/modules/field/field.default.inc b/core/modules/field/field.default.inc
index cb49bdb..ab4bcdd 100644
--- a/core/modules/field/field.default.inc
+++ b/core/modules/field/field.default.inc
@@ -160,8 +160,8 @@ function field_default_prepare_view($entity_type, $entities, $field, $instances,

   foreach ($modules as $module) {
     // Invoke hook_field_formatter_prepare_view().
-    $function = $module . '_field_formatter_prepare_view';
-    if (function_exists($function)) {
+    if (module_hook($module, 'field_formatter_prepare_view')) {
+      $function = $module . '_field_formatter_prepare_view';
       $function($entity_type, $grouped_entities[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $grouped_displays[$module]);
     }
   }
@@ -205,8 +205,8 @@ function field_default_view($entity_type, $entity, $field, $instance, $langcode,
   if ($display['type'] !== 'hidden') {
     // Calling the formatter function through module_invoke() can have a
     // performance impact on pages with many fields and values.
-    $function = $display['module'] . '_field_formatter_view';
-    if (function_exists($function)) {
+    if (module_hook($display['module'], 'field_formatter_view')) {
+      $function = $display['module'] . '_field_formatter_view';
       $elements = $function($entity_type, $entity, $field, $instance, $langcode, $items, $display);

       if ($elements) {
diff --git a/core/modules/field/field.form.inc b/core/modules/field/field.form.inc
index be3685d..6a8bc3b 100644
--- a/core/modules/field/field.form.inc
+++ b/core/modules/field/field.form.inc
@@ -60,8 +60,8 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
     // make it the $delta value.
     else {
       $delta = isset($get_delta) ? $get_delta : 0;
-      $function = $instance['widget']['module'] . '_field_widget_form';
-      if (function_exists($function)) {
+      if (module_hook($instance['widget']['module'], 'field_widget_form')) {
+        $function = $instance['widget']['module'] . '_field_widget_form';
         $element = array(
           '#entity_type' => $instance['entity_type'],
           '#bundle' => $instance['bundle'],
@@ -170,8 +170,8 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,

   $field_elements = array();

-  $function = $instance['widget']['module'] . '_field_widget_form';
-  if (function_exists($function)) {
+  if (module_hook($instance['widget']['module'], 'field_widget_form')) {
+    $function = $instance['widget']['module'] . '_field_widget_form';
     for ($delta = 0; $delta <= $max; $delta++) {
       $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
       $element = array(
@@ -359,7 +359,7 @@ function field_default_form_errors($entity_type, $entity, $field, $instance, $la

   if (!empty($field_state['errors'])) {
     $function = $instance['widget']['module'] . '_field_widget_error';
-    $function_exists = function_exists($function);
+    $function_exists = module_hook($instance['widget']['module'], 'field_widget_error');

     // Locate the correct element in the the form.
     $element = drupal_array_get_nested_value($form_state['complete_form'], $field_state['array_parents']);
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 70b17f5..ec8b01d 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -420,6 +420,102 @@ function field_system_info_alter(&$info, $file, $type) {
 }

 /**
+ * Implements hook_hook_info().
+ */
+function field_hook_info() {
+  $field_hooks = array(
+    'field_access',
+    'field_attach_create_bundle',
+    'field_attach_delete',
+    'field_attach_delete_bundle',
+    'field_attach_delete_revision',
+    'field_attach_form',
+    'field_attach_insert',
+    'field_attach_load',
+    'field_attach_prepare_translation_alter',
+    'field_attach_preprocess_alter',
+    'field_attach_presave',
+    'field_attach_purge',
+    'field_attach_rename_bundle',
+    'field_attach_submit',
+    'field_attach_update',
+    'field_attach_validate',
+    'field_attach_view_alter',
+    'field_available_languages_alter',
+    'field_create_field',
+    'field_create_instance',
+    'field_delete',
+    'field_delete_field',
+    'field_delete_instance',
+    'field_delete_revision',
+    'field_display_alter',
+    // @todo http://drupal.org/node/968264
+    'field_display_ENTITY_TYPE_alter',
+    'field_extra_fields',
+    'field_extra_fields_alter',
+    'field_extra_fields_display_alter',
+    'field_formatter_info',
+    'field_formatter_info_alter',
+    'field_formatter_prepare_view',
+    'field_formatter_settings_form',
+    'field_formatter_settings_summary',
+    'field_formatter_view',
+    'field_info',
+    'field_info_alter',
+    'field_info_max_weight',
+    'field_insert',
+    'field_instance_settings_form',
+    'field_is_empty',
+    'field_language_alter',
+    'field_load',
+    'field_prepare_translation',
+    'field_prepare_view',
+    'field_presave',
+    'field_purge_field',
+    'field_purge_field_instance',
+    'field_read_field',
+    'field_read_instance',
+    'field_settings_form',
+    'field_storage_create_field',
+    'field_storage_delete',
+    'field_storage_delete_field',
+    'field_storage_delete_instance',
+    'field_storage_delete_revision',
+    'field_storage_details',
+    'field_storage_details_alter',
+    'field_storage_info',
+    'field_storage_info_alter',
+    'field_storage_load',
+    'field_storage_pre_insert',
+    'field_storage_pre_load',
+    'field_storage_pre_update',
+    'field_storage_purge',
+    'field_storage_purge_field',
+    'field_storage_purge_field_instance',
+    'field_storage_query',
+    'field_storage_update_field',
+    'field_storage_write',
+    'field_update',
+    'field_update_field',
+    'field_update_forbid',
+    'field_update_instance',
+    'field_validate',
+    'field_widget_error',
+    'field_widget_form',
+    'field_widget_info',
+    'field_widget_info_alter',
+    'field_widget_properties_alter',
+    // @todo http://drupal.org/node/968264
+    'field_widget_properties_ENTITY_TYPE_alter',
+    'field_widget_settings_form',
+  );
+  $hooks = array_fill_keys($field_hooks, array(
+    'group' => 'field',
+  ));
+  return $hooks;
+}
+
+/**
  * Implements hook_flush_caches().
  */
 function field_flush_caches() {
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index 6fd55b3..a52a041 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -1558,9 +1558,9 @@ function field_ui_field_settings_form($form, &$form_state, $instance) {
   // responsible for not returning settings that cannot be changed if
   // the field already has data.
   $form['field']['settings'] = array();
-  $additions = module_invoke($field['module'], 'field_settings_form', $field, $instance, $has_data);
-  if (is_array($additions)) {
-    $form['field']['settings'] = $additions;
+  if (module_hook($field['module'], 'field_settings_form')) {
+    $function = $field['module'] . '_field_settings_form';
+    $form['field']['settings'] = $function($field, $instance, $has_data, $form, $form_state);
   }
   if (empty($form['field']['settings'])) {
     $form['field']['settings'] = array(
@@ -1838,15 +1838,17 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
   );

   // Add additional field instance settings from the field module.
-  $additions = module_invoke($field['module'], 'field_instance_settings_form', $field, $instance);
-  if (is_array($additions)) {
-    $form['instance']['settings'] = $additions;
+  $form['instance']['settings'] = array();
+  if (module_hook($field['module'], 'field_instance_settings_form')) {
+    $function = $field['module'] . '_field_instance_settings_form';
+    $form['instance']['settings'] = $function($field, $instance, $form, $form_state);
   }

   // Add additional widget settings from the widget module.
-  $additions = module_invoke($widget_type['module'], 'field_widget_settings_form', $field, $instance);
-  if (is_array($additions)) {
-    $form['instance']['widget']['settings'] = $additions;
+  $form['instance']['widget']['settings'] = array();
+  if (module_hook($widget_type['module'], 'field_widget_settings_form')) {
+    $function = $widget_type['module'] . '_field_widget_settings_form';
+    $form['instance']['widget']['settings'] = $function($field, $instance, $form, $form_state);
     $form['instance']['widget']['active']['#value'] = 1;
   }

@@ -1889,9 +1891,10 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
   // Add additional field type settings. The field type module is
   // responsible for not returning settings that cannot be changed if
   // the field already has data.
-  $additions = module_invoke($field['module'], 'field_settings_form', $field, $instance, $has_data);
-  if (is_array($additions)) {
-    $form['field']['settings'] = $additions;
+  $form['field']['settings'] = array();
+  if (module_hook($field['module'], 'field_settings_form')) {
+    $function = $field['module'] . '_field_settings_form';
+    $form['field']['settings'] = $function($field, $instance, $has_data, $form, $form_state);
   }

   $form['actions'] = array('#type' => 'actions');
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index 2340125..3d8d9ff 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -31,11 +31,15 @@
  *   The instance structure being configured.
  * @param $has_data
  *   TRUE if the field already has data, FALSE if not.
+ * @param $complete_form
+ *   The form structure of field_ui_field_edit_form().
+ * @param $form_state
+ *   The current state of the form.
  *
  * @return
  *   The form definition for the field settings.
  */
-function hook_field_settings_form($field, $instance, $has_data) {
+function hook_field_settings_form($field, $instance, $has_data, $complete_form, &$form_state) {
   $settings = $field['settings'];
   $form['max_length'] = array(
     '#type' => 'textfield',
@@ -58,11 +62,15 @@ function hook_field_settings_form($field, $instance, $has_data) {
  *   The field structure being configured.
  * @param $instance
  *   The instance structure being configured.
+ * @param $complete_form
+ *   The form structure of field_ui_field_edit_form().
+ * @param $form_state
+ *   The current state of the form.
  *
  * @return
  *   The form definition for the field instance settings.
  */
-function hook_field_instance_settings_form($field, $instance) {
+function hook_field_instance_settings_form($field, $instance, $complete_form, &$form_state) {
   $settings = $instance['settings'];

   $form['text_processing'] = array(
@@ -100,11 +108,15 @@ function hook_field_instance_settings_form($field, $instance) {
  *   The field structure being configured.
  * @param $instance
  *   The instance structure being configured.
+ * @param $complete_form
+ *   The form structure of field_ui_field_edit_form().
+ * @param $form_state
+ *   The current state of the form.
  *
  * @return
  *   The form definition for the widget settings.
  */
-function hook_field_widget_settings_form($field, $instance) {
+function hook_field_widget_settings_form($field, $instance, $complete_form, &$form_state) {
   $widget = $instance['widget'];
   $settings = $widget['settings'];

diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index 7f5906e..a340eda 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -71,9 +71,13 @@ function file_field_settings_form($field, $instance, $has_data) {
 /**
  * Implements hook_field_instance_settings_form().
  */
-function file_field_instance_settings_form($field, $instance) {
+function file_field_instance_settings_form($field, $instance, $complete_form, &$form_state) {
   $settings = $instance['settings'];

+  // #element_validate handlers are defined in this file, so ensure that it is
+  // loaded when the form is processed from cache.
+  form_load_include($form_state, 'inc', 'file', 'file.field');
+
   $form['file_directory'] = array(
     '#type' => 'textfield',
     '#title' => t('File directory'),
@@ -467,6 +471,9 @@ function file_field_widget_form(&$form, &$form_state, $field, $instance, $langco
     // Allows this field to return an array instead of a single value.
     '#extended' => TRUE,
   );
+  // file_field_widget_process() is defined in this file, so ensure that it is
+  // loaded when the form is processed.
+  form_load_include($form_state, 'inc', 'file', 'file.field');

   if ($field['cardinality'] == 1) {
     // Set the default value.
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 204a48f..feeb718 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -5,9 +5,6 @@
  * Defines a "managed_file" Form API field and a "file" field for Field module.
  */

-// Load all Field module hooks for File.
-require_once DRUPAL_ROOT . '/core/modules/file/file.field.inc';
-
 /**
  * Implements hook_help().
  */
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index c3ac1d5..f5b53d2 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -5,6 +5,10 @@
  * Implement an image field, based on the file module's file field.
  */

+// Image field depends on file field, so all field hook implementations of File
+// module need to be loaded.
+require_once DRUPAL_ROOT . '/core/modules/file/file.field.inc';
+
 /**
  * Implements hook_field_info().
  */
@@ -68,11 +72,15 @@ function image_field_settings_form($field, $instance) {
 /**
  * Implements hook_field_instance_settings_form().
  */
-function image_field_instance_settings_form($field, $instance) {
+function image_field_instance_settings_form($field, $instance, $complete_form, &$form_state) {
   $settings = $instance['settings'];

   // Use the file field instance settings form as a basis.
-  $form = file_field_instance_settings_form($field, $instance);
+  $form = file_field_instance_settings_form($field, $instance, $complete_form, $form_state);
+
+  // #element_validate handlers are defined in this file, so ensure that it is
+  // loaded when the form is processed from cache.
+  form_load_include($form_state, 'inc', 'image', 'image.field');

   // Add maximum and minimum resolution settings.
   $max_resolution = explode('x', $settings['max_resolution']) + array('', '');
@@ -280,12 +288,12 @@ function image_field_widget_info() {
 /**
  * Implements hook_field_widget_settings_form().
  */
-function image_field_widget_settings_form($field, $instance) {
+function image_field_widget_settings_form($field, $instance, $complete_form, &$form_state) {
   $widget = $instance['widget'];
   $settings = $widget['settings'];

   // Use the file widget settings form.
-  $form = file_field_widget_settings_form($field, $instance);
+  $form = file_field_widget_settings_form($field, $instance, $complete_form, $form_state);

   $form['preview_image_style'] = array(
     '#title' => t('Preview image style'),
@@ -326,6 +334,9 @@ function image_field_widget_form(&$form, &$form_state, $field, $instance, $langc
     // Add all extra functionality provided by the image widget.
     $elements[$delta]['#process'][] = 'image_field_widget_process';
   }
+  // image_field_widget_process() is defined in this file, so ensure that it is
+  // loaded when the form is processed.
+  form_load_include($form_state, 'inc', 'image', 'image.field');

   if ($field['cardinality'] == 1) {
     // If there's only one field, return it as delta 0.
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 54d98eb..dc3a195 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -30,9 +30,6 @@ define('IMAGE_STORAGE_EDITABLE', IMAGE_STORAGE_NORMAL | IMAGE_STORAGE_OVERRIDE);
  */
 define('IMAGE_STORAGE_MODULE', IMAGE_STORAGE_OVERRIDE | IMAGE_STORAGE_DEFAULT);

-// Load all Field module hooks for Image.
-require_once DRUPAL_ROOT . '/core/modules/image/image.field.inc';
-
 /**
  * Implement of hook_help().
  */
