summaryrefslogtreecommitdiffstatshomepage
path: root/py/runtime.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-03-26 21:47:19 +0000
committerDamien George <damien.p.george@gmail.com>2014-03-26 21:47:19 +0000
commit9b196cddab80e24b9ce66b1c922cb757b11fb16a (patch)
tree0906c4b454a984c51218aa8e0a1c1d9073e4cc77 /py/runtime.c
parentc12b2213c16ba8839981c362c4d5f133a84b374b (diff)
downloadmicropython-9b196cddab80e24b9ce66b1c922cb757b11fb16a.tar.gz
micropython-9b196cddab80e24b9ce66b1c922cb757b11fb16a.zip
Remove mp_obj_type_t.methods entry and use .locals_dict instead.
Originally, .methods was used for methods in a ROM class, and locals_dict for methods in a user-created class. That distinction is unnecessary, and we can use locals_dict for ROM classes now that we have ROMable maps. This removes an entry in the bloated mp_obj_type_t struct, saving a word for each ROM object and each RAM object. ROM objects that have a methods table (now a locals_dict) need an extra word in total (removed the methods pointer (1 word), no longer need the sentinel (2 words), but now need an mp_obj_dict_t wrapper (4 words)). But RAM objects save a word because they never used the methods entry. Overall the ROM usage is down by a few hundred bytes, and RAM usage is down 1 word per user-defined type/class. There is less code (no need to check 2 tables), and now consistent with the way ROM modules have their tables initialised. Efficiency is very close to equivaluent.
Diffstat (limited to 'py/runtime.c')
-rw-r--r--py/runtime.c37
1 files changed, 18 insertions, 19 deletions
diff --git a/py/runtime.c b/py/runtime.c
index 247a78fe1a..1f4a524b70 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -845,25 +845,24 @@ STATIC void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
} else if (type->load_attr == NULL) {
// generic method lookup if type didn't provide a specific one
// this is a lookup in the object (ie not class or type)
- const mp_method_t *meth = type->methods;
- if (meth != NULL) {
- for (; meth->name != MP_QSTR_NULL; meth++) {
- if (meth->name == attr) {
- // check if the methods are functions, static or class methods
- // see http://docs.python.org/3.3/howto/descriptor.html
- if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_staticmethod)) {
- // return just the function
- dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
- } else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
- // return a bound method, with self being the type of this object
- dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
- dest[1] = mp_obj_get_type(base);
- } else {
- // return a bound method, with self being this object
- dest[0] = (mp_obj_t)meth->fun;
- dest[1] = base;
- }
- break;
+ if (type->locals_dict != NULL) {
+ assert(MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)); // Micro Python restriction, for now
+ mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
+ mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
+ if (elem != NULL) {
+ // check if the methods are functions, static or class methods
+ // see http://docs.python.org/3.3/howto/descriptor.html
+ if (MP_OBJ_IS_TYPE(elem->value, &mp_type_staticmethod)) {
+ // return just the function
+ dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
+ } else if (MP_OBJ_IS_TYPE(elem->value, &mp_type_classmethod)) {
+ // return a bound method, with self being the type of this object
+ dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
+ dest[1] = mp_obj_get_type(base);
+ } else {
+ // return a bound method, with self being this object
+ dest[0] = (mp_obj_t)elem->value;
+ dest[1] = base;
}
}
}