Optimizations and one intentional loophole by Jim Fulton.

The optimizations consist mostly of using local variables to cache
methods or instance variables used a lot (e.g. "self.write").

The loopholes allows marshalling extension types as long as they have
a __class__ attribute (in which case they may support the rest of the
class piclking protocol as well).  This allows pickling MESS extension
types.
diff --git a/Lib/pickle.py b/Lib/pickle.py
index 8f5da40..dde3dee 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -126,7 +126,7 @@
 I have no answers.  Garbage Collection may also become a problem here.)
 """
 
-__version__ = "1.5"			# Code version
+__version__ = "1.6"			# Code version
 
 from types import *
 import string
@@ -200,8 +200,11 @@
 		try:
 			f = self.dispatch[t]
 		except KeyError:
-			raise PicklingError, \
-			      "can't pickle %s objects" % `t.__name__`
+		        if hasattr(object, '__class__'):
+			        f = self.dispatch[InstanceType]
+			else:
+			        raise PicklingError, \
+				"can't pickle %s objects" % `t.__name__`
 		f(self, object)
 
 	def persistent_id(self, object):
@@ -234,66 +237,75 @@
 
 	def save_tuple(self, object):
 		d = id(object)
-		self.write(MARK)
+		write = self.write
+		save = self.save
+		has_key = self.memo.has_key
+		write(MARK)
 		n = len(object)
 		for k in range(n):
-			self.save(object[k])
-			if self.memo.has_key(d):
+			save(object[k])
+			if has_key(d):
 				# Saving object[k] has saved us!
 				while k >= 0:
-					self.write(POP)
+					write(POP)
 					k = k-1
-				self.write(GET + `d` + '\n')
+				write(GET + `d` + '\n')
 				break
 		else:
-			self.write(TUPLE + PUT + `d` + '\n')
+			write(TUPLE + PUT + `d` + '\n')
 			self.memo[d] = object
 	dispatch[TupleType] = save_tuple
 
 	def save_list(self, object):
 		d = id(object)
-		self.write(MARK)
+		write = self.write
+		save = self.save
+		write(MARK)
 		n = len(object)
 		for k in range(n):
 			item = object[k]
 			if not safe(item):
 				break
-			self.save(item)
+			save(item)
 		else:
 			k = n
-		self.write(LIST + PUT + `d` + '\n')
+		write(LIST + PUT + `d` + '\n')
 		self.memo[d] = object
 		for k in range(k, n):
 			item = object[k]
-			self.save(item)
-			self.write(APPEND)
+			save(item)
+			write(APPEND)
 	dispatch[ListType] = save_list
 
 	def save_dict(self, object):
 		d = id(object)
-		self.write(MARK)
+		write = self.write
+		save = self.save
+		write(MARK)
 		items = object.items()
 		n = len(items)
 		for k in range(n):
 			key, value = items[k]
 			if not safe(key) or not safe(value):
 				break
-			self.save(key)
-			self.save(value)
+			save(key)
+			save(value)
 		else:
 			k = n
 		self.write(DICT + PUT + `d` + '\n')
 		self.memo[d] = object
 		for k in range(k, n):
 			key, value = items[k]
-			self.save(key)
-			self.save(value)
-			self.write(SETITEM)
+			save(key)
+			save(value)
+			write(SETITEM)
 	dispatch[DictionaryType] = save_dict
 
 	def save_inst(self, object):
 		d = id(object)
 		cls = object.__class__
+		write = self.write
+		save = self.save
 		module = whichmodule(cls)
 		name = cls.__name__
 		if hasattr(object, '__getinitargs__'):
@@ -301,11 +313,11 @@
 			len(args) # XXX Assert it's a sequence
 		else:
 			args = ()
-		self.write(MARK)
+		write(MARK)
 		for arg in args:
-			self.save(arg)
-		self.write(INST + module + '\n' + name + '\n' +
-			   PUT + `d` + '\n')
+			save(arg)
+		write(INST + module + '\n' + name + '\n' +
+		      PUT + `d` + '\n')
 		self.memo[d] = object
 		try:
 			getstate = object.__getstate__
@@ -313,8 +325,8 @@
 			stuff = object.__dict__
 		else:
 			stuff = getstate()
-		self.save(stuff)
-		self.write(BUILD)
+		save(stuff)
+		write(BUILD)
 	dispatch[InstanceType] = save_inst
 
 	def save_class(self, object):
@@ -361,16 +373,21 @@
 	def load(self):
 		self.mark = ['spam'] # Any new unique object
 		self.stack = []
+		self.append = self.stack.append
+		read = self.read
+		dispatch = self.dispatch
 		try:
 			while 1:
-				key = self.read(1)
-				self.dispatch[key](self)
+				key = read(1)
+				dispatch[key](self)
 		except STOP, value:
 			return value
 
 	def marker(self):
-		k = len(self.stack)-1
-		while self.stack[k] != self.mark: k = k-1
+	        stack = self.stack
+		mark = self.mark
+		k = len(stack)-1
+		while stack[k] is not mark: k = k-1
 		return k
 
 	dispatch = {}
@@ -381,27 +398,28 @@
 
 	def load_persid(self):
 		pid = self.readline()[:-1]
-		self.stack.append(self.persistent_load(pid))
+		self.append(self.persistent_load(pid))
 	dispatch[PERSID] = load_persid
 
 	def load_none(self):
-		self.stack.append(None)
+		self.append(None)
 	dispatch[NONE] = load_none
 
 	def load_int(self):
-		self.stack.append(string.atoi(self.readline()[:-1], 0))
+		self.append(string.atoi(self.readline()[:-1], 0))
 	dispatch[INT] = load_int
 
 	def load_long(self):
-		self.stack.append(string.atol(self.readline()[:-1], 0))
+		self.append(string.atol(self.readline()[:-1], 0))
 	dispatch[LONG] = load_long
 
 	def load_float(self):
-		self.stack.append(string.atof(self.readline()[:-1]))
+		self.append(string.atof(self.readline()[:-1]))
 	dispatch[FLOAT] = load_float
 
 	def load_string(self):
-		self.stack.append(eval(self.readline()[:-1]))
+		self.append(eval(self.readline()[:-1],
+				 {'__builtins__': {}})) # Let's be careful
 	dispatch[STRING] = load_string
 
 	def load_tuple(self):
@@ -433,14 +451,14 @@
 		name = self.readline()[:-1]
 		klass = self.find_class(module, name)
 		value = apply(klass, args)
-		self.stack.append(value)
+		self.append(value)
 	dispatch[INST] = load_inst
 
 	def load_class(self):
 		module = self.readline()[:-1]
 		name = self.readline()[:-1]
 		klass = self.find_class(module, name)
-		self.stack.append(klass)
+		self.append(klass)
 		return klass
 	dispatch[CLASS] = load_class
 
@@ -453,7 +471,9 @@
 			      "Failed to import class %s from module %s" % \
 			      (name, module)
 		klass = env[name]
-		if type(klass) != ClassType:
+		# if type(klass) != ClassType:
+		if (type(klass) is FunctionType or
+		    type(klass) is BuiltinFunctionType):
 			raise SystemError, \
 			 "Imported object %s from module %s is not a class" % \
 			 (name, module)
@@ -464,11 +484,11 @@
 	dispatch[POP] = load_pop
 
 	def load_dup(self):
-		stack.append(stack[-1])
+		self.append(stack[-1])
 	dispatch[DUP] = load_dup
 
 	def load_get(self):
-		self.stack.append(self.memo[self.readline()[:-1]])
+		self.append(self.memo[self.readline()[:-1]])
 	dispatch[GET] = load_get
 
 	def load_put(self):
@@ -476,35 +496,39 @@
 	dispatch[PUT] = load_put
 
 	def load_append(self):
-		value = self.stack[-1]
-		del self.stack[-1]
-		list = self.stack[-1]
+	        stack = self.stack
+		value = stack[-1]
+		del stack[-1]
+		list = stack[-1]
 		list.append(value)
 	dispatch[APPEND] = load_append
 
 	def load_setitem(self):
-		value = self.stack[-1]
-		key = self.stack[-2]
-		del self.stack[-2:]
-		dict = self.stack[-1]
+	        stack = self.stack
+		value = stack[-1]
+		key = stack[-2]
+		del stack[-2:]
+		dict = stack[-1]
 		dict[key] = value
 	dispatch[SETITEM] = load_setitem
 
 	def load_build(self):
-		value = self.stack[-1]
-		del self.stack[-1]
-		inst = self.stack[-1]
+	        stack = self.stack
+		value = stack[-1]
+		del stack[-1]
+		inst = stack[-1]
 		try:
 			setstate = inst.__setstate__
 		except AttributeError:
+		        instdict = inst.__dict__
 			for key in value.keys():
-				inst.__dict__[key] = value[key]
+				instdict[key] = value[key]
 		else:
 			setstate(value)
 	dispatch[BUILD] = load_build
 
 	def load_mark(self):
-		self.stack.append(self.mark)
+		self.append(self.mark)
 	dispatch[MARK] = load_mark
 
 	def load_stop(self):
@@ -516,12 +540,13 @@
 
 # Shorthands
 
+from StringIO import StringIO
+
 def dump(object, file):
 	Pickler(file).dump(object)
 
 def dumps(object):
-	import StringIO
-	file = StringIO.StringIO()
+	file = StringIO()
 	Pickler(file).dump(object)
 	return file.getvalue()
 
@@ -529,8 +554,7 @@
 	return Unpickler(file).load()
 
 def loads(str):
-	import StringIO
-	file = StringIO.StringIO(str)
+	file = StringIO(str)
 	return Unpickler(file).load()
 
 
@@ -545,7 +569,7 @@
 	c = C()
 	c.foo = 1
 	c.bar = 2L
-	x = [0,1,2,3]
+	x = [0, 1, 2, 3]
 	y = ('abc', 'abc', c, c)
 	x.append(y)
 	x.append(y)