Index: Python/ceval.c
===================================================================
--- Python/ceval.c	(revision 42002)
+++ Python/ceval.c	(working copy)
@@ -1793,14 +1793,21 @@
 		case STORE_GLOBAL:
 			w = GETITEM(names, oparg);
 			v = POP();
-			err = PyDict_SetItem(f->f_globals, w, v);
+			if (PyDict_CheckExact(f->f_globals))
+				err = PyDict_SetItem(f->f_globals, w, v);
+			else
+				err = PyObject_SetItem(f->f_globals, w, v);
 			Py_DECREF(v);
 			if (err == 0) continue;
 			break;
 
 		case DELETE_GLOBAL:
 			w = GETITEM(names, oparg);
-			if ((err = PyDict_DelItem(f->f_globals, w)) != 0)
+			if (PyDict_CheckExact(f->f_globals))
+				err = PyDict_DelItem(f->f_globals, w); 
+			else
+				err = PyObject_DelItem(f->f_globals, w); 
+			if (err) 
 				format_exc_check_arg(
 				    PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w);
 			break;
@@ -1826,9 +1833,15 @@
 				}
 			}
 			if (x == NULL) {
-				x = PyDict_GetItem(f->f_globals, w);
+				if (PyDict_CheckExact(f->f_globals)) {
+					x = PyDict_GetItem(f->f_globals, w);
+					Py_XINCREF(x);
+				} else {
+					x = PyObject_GetItem(f->f_globals, w);
+				}
 				if (x == NULL) {
 					x = PyDict_GetItem(f->f_builtins, w);
+					Py_XINCREF(x);
 					if (x == NULL) {
 						format_exc_check_arg(
 							    PyExc_NameError,
@@ -1836,39 +1849,48 @@
 						break;
 					}
 				}
-				Py_INCREF(x);
 			}
 			PUSH(x);
 			continue;
 
 		case LOAD_GLOBAL:
 			w = GETITEM(names, oparg);
-			if (PyString_CheckExact(w)) {
-				/* Inline the PyDict_GetItem() calls.
-				   WARNING: this is an extreme speed hack.
-				   Do not try this at home. */
-				long hash = ((PyStringObject *)w)->ob_shash;
-				if (hash != -1) {
-					PyDictObject *d;
-					d = (PyDictObject *)(f->f_globals);
-					x = d->ma_lookup(d, w, hash)->me_value;
-					if (x != NULL) {
-						Py_INCREF(x);
-						PUSH(x);
-						continue;
+			if (PyDict_CheckExact(f->f_globals)) {
+				if (PyString_CheckExact(w)) {
+					/* Inline the PyDict_GetItem() calls.
+					   WARNING: this is an extreme speed hack.
+					   Do not try this at home. */
+					long hash = ((PyStringObject *)w)->ob_shash;
+					if (hash != -1) {
+						PyDictObject *d;
+						d = (PyDictObject *)(f->f_globals);
+						x = d->ma_lookup(d, w, hash)->me_value;
+						if (x != NULL) {
+							Py_INCREF(x);
+							PUSH(x);
+							continue;
+						}
+						d = (PyDictObject *)(f->f_builtins);
+						x = d->ma_lookup(d, w, hash)->me_value;
+						if (x != NULL) {
+							Py_INCREF(x);
+							PUSH(x);
+							continue;
+						}
+						goto load_global_error;
 					}
-					d = (PyDictObject *)(f->f_builtins);
-					x = d->ma_lookup(d, w, hash)->me_value;
-					if (x != NULL) {
-						Py_INCREF(x);
-						PUSH(x);
-						continue;
-					}
-					goto load_global_error;
 				}
+				/* This is the un-inlined version of the code above */
+				x = PyDict_GetItem(f->f_globals, w);
+				Py_XINCREF(x);
+			} else {
+				x = PyObject_GetItem(f->f_globals, w);
+				if (x == NULL) {
+					if (!PyErr_ExceptionMatches(PyExc_KeyError))
+						break;
+					PyErr_Clear();
+				}
 			}
-			/* This is the un-inlined version of the code above */
-			x = PyDict_GetItem(f->f_globals, w);
 			if (x == NULL) {
 				x = PyDict_GetItem(f->f_builtins, w);
 				if (x == NULL) {
@@ -1878,8 +1900,8 @@
 						    GLOBAL_NAME_ERROR_MSG, w);
 					break;
 				}
+				Py_INCREF(x);
 			}
-			Py_INCREF(x);
 			PUSH(x);
 			continue;
 
Index: Lib/test/test_dictsubclassexec.py
===================================================================
--- Lib/test/test_dictsubclassexec.py	(revision 0)
+++ Lib/test/test_dictsubclassexec.py	(revision 0)
@@ -0,0 +1,101 @@
+import unittest
+from test import test_support
+
+class DictSubclass(dict):
+    get_notify_func = None
+    def __getitem__(self, key):
+        if self.get_notify_func:
+            self.get_notify_func(key)
+        return dict.__getitem__(self, key)
+
+    set_notify_func = None
+    def __setitem__(self, key, value):
+        if self.set_notify_func:
+            self.set_notify_func(key)
+        return dict.__setitem__(self, key, value)
+
+    del_notify_func = None
+    def __delitem__(self, key):
+        if self.del_notify_func:
+            self.del_notify_func(key)
+        return dict.__delitem__(self, key)
+
+class DictSubclassExecTest(unittest.TestCase):
+    def test_subclassexec_setlocal(self):
+        d = DictSubclass()
+        l = []
+        d.set_notify_func = l.append
+        exec "a = 1" in d
+        d.set_notify_func = None
+        self.assert_(d['a'] == 1)
+        self.assert_('a' in l)
+
+    def test_subclassexec_getlocal(self):
+        d = DictSubclass()
+        l = []
+        d.get_notify_func = l.append
+        exec "a = 1; a" in d
+        d.get_notify_func = None
+        self.assert_(d['a'] == 1)
+        self.assert_('a' in l)
+
+    def test_subclassexec_dellocal(self):
+        d = DictSubclass()
+        l = []
+        d.del_notify_func = l.append
+        exec "a = 1; del a" in d
+        d.del_notify_func = None
+        self.assert_(not d.has_key('a'))
+        self.assert_('a' in l)
+
+    def test_subclassexec_setglobal(self):
+        d = DictSubclass()
+        l = []
+        d.set_notify_func = l.append
+        exec "a = 1\ndef foo():\n\tglobal a\n\tpass" in d
+        d.set_notify_func = None
+        self.assert_(d['a'] == 1)
+        self.assert_('a' in l)
+
+    def test_subclassexec_getglobal(self):
+        d = DictSubclass()
+        l = []
+        d.get_notify_func = l.append
+        exec "a = 1; a\ndef foo():\n\tglobal a\n\tpass" in d
+        d.get_notify_func = None
+        self.assert_(d['a'] == 1)
+        self.assert_('a' in l)
+
+    def test_subclassexec_delglobal(self):
+        d = DictSubclass()
+        l = []
+        d.del_notify_func = l.append
+        exec "a = 1; del a\ndef foo():\n\tglobal a\n\tpass" in d
+        d.del_notify_func = None
+        self.assert_(not d.has_key('a'))
+        self.assert_('a' in l)
+
+    def test_subclassexec_getfallthrough(self):
+        ld = DictSubclass()
+        ll = []
+        ld.get_notify_func = ll.append
+        gd = DictSubclass()
+        gl = []
+        gd.get_notify_func = gl.append
+        gd['a'] = 1
+        exec 'b = a' in gd, ld
+        gd.del_notify_func = None
+        ld.del_notify_func = None
+        self.assert_(ld['b'] == 1)
+        self.assert_('a' in ll)
+        self.assert_('a' in gl)
+
+
+def test_main():
+        test_support.run_unittest(
+                DictSubclassExecTest,
+        )
+
+if __name__ == "__main__":
+        test_main()
+







