diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index 9ae38383ffe7c3bf3b1857f253b1e1aa3a43ea54..0561f88d15e99f81c44d9dfb74bf82ce6c0efcb6 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,13 @@
+2010-10-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc-private/runtime.h (__objc_update_classes_with_methods): New.
+	* class.c (__objc_update_classes_with_methods): New.
+	(objc_getClassList): Do not lock the class lock.
+	* methods.c (method_exchangeImplementations): New.
+	(method_setImplementation): New.
+	* objc/runtime.h (method_setImplementation): New.
+	(method_exchangeImplementations): New.
+	
 2010-10-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* Protocol.m: Include objc/runtime.h and
diff --git a/libobjc/class.c b/libobjc/class.c
index 4eb86761ee868b2769db3d1eba5811e5622a9804..8c6f989a8e9bfee366b3119c5ef026909fddadf7 100644
--- a/libobjc/class.c
+++ b/libobjc/class.c
@@ -93,6 +93,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "objc/thr.h"
 #include "objc-private/module-abi-8.h"  /* For CLS_ISCLASS and similar.  */
 #include "objc-private/runtime.h"       /* the kitchen sink */
+#include "objc-private/sarray.h"        /* For sarray_put_at_safe.  */
 #include <string.h>                     /* For memset */
 
 /* We use a table which maps a class name to the corresponding class
@@ -546,8 +547,6 @@ objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn)
   /* Iterate over all entries in the table.  */
   int hash, count = 0;
 
-  objc_mutex_lock (__class_table_lock); 
-
   for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
     {
       class_node_ptr node = class_table_array[hash];
@@ -560,7 +559,6 @@ objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn)
 		returnValue[count] = node->pointer;
 	      else
 		{
-		  objc_mutex_unlock (__class_table_lock);
 		  return count;
 		}
 	    }
@@ -569,7 +567,6 @@ objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn)
 	}
     }
   
-  objc_mutex_unlock (__class_table_lock);
   return count;
 }
 
@@ -647,6 +644,62 @@ objc_next_class (void **enum_state)
   return class;
 }
 
+/* This is used when the implementation of a method changes.  It goes
+   through all classes, looking for the ones that have these methods
+   (either method_a or method_b; method_b can be NULL), and reloads
+   the implementation for these.  You should call this with the
+   runtime mutex already locked.  */
+void
+__objc_update_classes_with_methods (struct objc_method *method_a, struct objc_method *method_b)
+{
+  int hash;
+
+  /* Iterate over all classes.  */
+  for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
+    {
+      class_node_ptr node = class_table_array[hash];
+      
+      while (node != NULL)
+	{
+	  /* Iterate over all methods in the class.  */
+	  Class class = node->pointer;
+	  struct objc_method_list * method_list = class->methods;
+
+	  while (method_list)
+	    {
+	      int i;
+
+	      for (i = 0; i < method_list->method_count; ++i)
+		{
+		  struct objc_method *method = &method_list->method_list[i];
+
+		  /* If the method is one of the ones we are looking
+		     for, update the implementation.  */
+		  if (method == method_a)
+		    {
+		      sarray_at_put_safe (class->dtable,
+					  (sidx) method_a->method_name->sel_id,
+					  method_a->method_imp);
+		    }
+
+		  if (method == method_b)
+		    {
+		      if (method_b != NULL)
+			{
+			  sarray_at_put_safe (class->dtable,
+					      (sidx) method_b->method_name->sel_id,
+					      method_b->method_imp);
+			}
+		    }
+		}
+	  
+	      method_list = method_list->method_next;
+	    }
+	  node = node->next;
+	}
+    }
+}
+
 /* Resolve super/subclass links for all classes.  The only thing we
    can be sure of is that the class_pointer for class objects point to
    the right meta class objects.  */
diff --git a/libobjc/methods.c b/libobjc/methods.c
index 65939a6d5cd7ed21cb71f1453d91818e7fa13c41..b4faee533c28a008f6b7ad75035a833f21399c4b 100644
--- a/libobjc/methods.c
+++ b/libobjc/methods.c
@@ -124,3 +124,54 @@ class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods)
 
   return returnValue;
 }
+
+IMP
+method_setImplementation (struct objc_method * method, IMP implementation)
+{
+  IMP old_implementation;
+
+  if (method == NULL  ||  implementation == NULL)
+    return NULL;
+
+  /* We lock the runtime mutex so that concurrent calls to change the
+     same method won't conflict with each other.  */
+  objc_mutex_lock (__objc_runtime_mutex);
+
+  old_implementation = method->method_imp;
+  method->method_imp = implementation;
+
+  /* That was easy :-).  But now we need to find all classes that use
+     this method, and update the IMP in the dispatch tables.  */
+  __objc_update_classes_with_methods (method, NULL);
+
+  objc_mutex_unlock (__objc_runtime_mutex);
+
+  return old_implementation;
+}
+
+void
+method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b)
+{
+  IMP old_implementation_a;
+  IMP old_implementation_b;
+
+  if (method_a == NULL  ||  method_b == NULL)
+    return;
+
+  /* We lock the runtime mutex so that concurrent calls to exchange
+     similar methods won't conflict with each other.  Each of them
+     should be atomic.  */
+  objc_mutex_lock (__objc_runtime_mutex);
+
+  old_implementation_a = method_a->method_imp;
+  old_implementation_b = method_b->method_imp;
+
+  method_a->method_imp = old_implementation_b;
+  method_b->method_imp = old_implementation_a;
+
+  /* That was easy :-).  But now we need to find all classes that use
+     these methods, and update the IMP in the dispatch tables.  */
+  __objc_update_classes_with_methods (method_a, method_b);
+
+  objc_mutex_unlock (__objc_runtime_mutex);
+}
diff --git a/libobjc/objc-private/runtime.h b/libobjc/objc-private/runtime.h
index 6794d1815130015259b2d1d180107aae200db84e..ff924becd937f74477ac67ee86edf843b5d94aef 100644
--- a/libobjc/objc-private/runtime.h
+++ b/libobjc/objc-private/runtime.h
@@ -74,6 +74,9 @@ extern void class_add_method_list(Class, struct objc_method_list *);
 extern void __objc_register_instance_methods_to_class(Class);
 extern struct objc_method * search_for_method_in_list(struct objc_method_list * list, SEL op);
 
+extern void
+__objc_update_classes_with_methods (struct objc_method *method_a, struct objc_method *method_b); /* class.c */
+
 /* True when class links has been resolved */     
 extern BOOL __objc_class_links_resolved;
 
diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h
index 938033148ae42a945f67e2cd0ee838431e45cf31..bb241acd5b33f198039c8b66358f8f7e231c5368 100644
--- a/libobjc/objc/runtime.h
+++ b/libobjc/objc/runtime.h
@@ -545,7 +545,26 @@ objc_EXPORT void method_getReturnType (Method method, char *returnValue,
 objc_EXPORT void method_getArgumentType (Method method, unsigned int argumentNumber,
 					 char *returnValue, size_t returnValueSize);
 
-
+/* Change the implementation of the method.  It also searches all
+   classes for any class implementing the method, and replaces the
+   existing implementation with the new one.  For that to work,
+   'method' must be a method returned by class_getInstanceMethod() or
+   class_getClassMethod() as the matching is done by comparing the
+   pointers; in that case, only the implementation in the class is
+   modified.  Return the previous implementation that has been
+   replaced.  If method or implementation is NULL, do nothing and
+   return NULL.  */
+objc_EXPORT IMP
+method_setImplementation (Method method, IMP implementation);
+
+/* Swap the implementation of two methods in a single, atomic
+   operation.  This is equivalent to getting the implementation of
+   each method and then calling method_setImplementation() on the
+   other one.  For this to work, the two methods must have been
+   returned by class_getInstanceMethod() or class_getClassMethod().
+   If 'method_a' or 'method_b' is NULL, do nothing.  */
+objc_EXPORT void
+method_exchangeImplementations (Method method_a, Method method_b);
 
 /** Implementation: the following functions are in protocols.c.  */