Skip to content

Commit bfc2092

Browse files
committed
py/modsys: Initial implementation of sys.getsizeof().
Implemented as a new MP_UNARY_OP. This patch adds support lists, dicts and instances.
1 parent 7d4a2f7 commit bfc2092

File tree

8 files changed

+49
-1
lines changed

8 files changed

+49
-1
lines changed

py/modsys.c

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* The MIT License (MIT)
55
*
66
* Copyright (c) 2013, 2014 Damien P. George
7+
* Copyright (c) 2014-2017 Paul Sokolovsky
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -31,8 +32,11 @@
3132
#include "py/objtuple.h"
3233
#include "py/objstr.h"
3334
#include "py/objint.h"
35+
#include "py/objtype.h"
3436
#include "py/stream.h"
3537
#include "py/smallint.h"
38+
#include "py/runtime0.h"
39+
#include "py/runtime.h"
3640

3741
#if MICROPY_PY_SYS
3842

@@ -143,6 +147,11 @@ STATIC mp_obj_t mp_sys_exc_info(void) {
143147
MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info);
144148
#endif
145149

150+
STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) {
151+
return mp_unary_op(MP_UNARY_OP_SIZEOF, obj);
152+
}
153+
MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof);
154+
146155
STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
147156
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) },
148157

@@ -192,6 +201,9 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
192201
#if MICROPY_PY_SYS_EXC_INFO
193202
{ MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) },
194203
#endif
204+
#if MICROPY_PY_SYS_GETSIZEOF
205+
{ MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) },
206+
#endif
195207

196208
/*
197209
* Extensions to CPython

py/mpconfig.h

+5
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,11 @@ typedef double mp_float_t;
944944
#define MICROPY_PY_SYS_EXIT (1)
945945
#endif
946946

947+
// Whether to provide "sys.getsizeof" function
948+
#ifndef MICROPY_PY_SYS_GETSIZEOF
949+
#define MICROPY_PY_SYS_GETSIZEOF (0)
950+
#endif
951+
947952
// Whether to provide sys.{stdin,stdout,stderr} objects
948953
#ifndef MICROPY_PY_SYS_STDFILES
949954
#define MICROPY_PY_SYS_STDFILES (0)

py/objdict.c

+6
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) {
105105
switch (op) {
106106
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0);
107107
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);
108+
#if MICROPY_PY_SYS_GETSIZEOF
109+
case MP_UNARY_OP_SIZEOF: {
110+
size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc;
111+
return MP_OBJ_NEW_SMALL_INT(sz);
112+
}
113+
#endif
108114
default: return MP_OBJ_NULL; // op not supported
109115
}
110116
}

py/objlist.c

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
104104
switch (op) {
105105
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
106106
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
107+
#if MICROPY_PY_SYS_GETSIZEOF
108+
case MP_UNARY_OP_SIZEOF: {
109+
size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc;
110+
return MP_OBJ_NEW_SMALL_INT(sz);
111+
}
112+
#endif
107113
default: return MP_OBJ_NULL; // op not supported
108114
}
109115
}

py/objtype.c

+16
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,27 @@ const qstr mp_unary_op_method_name[] = {
339339
[MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,
340340
[MP_UNARY_OP_INVERT] = MP_QSTR___invert__,
341341
#endif
342+
#if MICROPY_PY_SYS_GETSIZEOF
343+
[MP_UNARY_OP_SIZEOF] = MP_QSTR_getsizeof,
344+
#endif
342345
[MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size
343346
};
344347

345348
STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
346349
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
350+
351+
#if MICROPY_PY_SYS_GETSIZEOF
352+
if (MP_UNLIKELY(op == MP_UNARY_OP_SIZEOF)) {
353+
// TODO: This doesn't count inherited objects (self->subobj)
354+
const mp_obj_type_t *native_base;
355+
size_t num_native_bases = instance_count_native_bases(mp_obj_get_type(self_in), &native_base);
356+
357+
size_t sz = sizeof(*self) + sizeof(*self->subobj) * num_native_bases
358+
+ sizeof(*self->members.table) * self->members.alloc;
359+
return MP_OBJ_NEW_SMALL_INT(sz);
360+
}
361+
#endif
362+
347363
qstr op_name = mp_unary_op_method_name[op];
348364
/* Still try to lookup native slot
349365
if (op_name == 0) {

py/runtime0.h

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ typedef enum {
5050
MP_UNARY_OP_NEGATIVE,
5151
MP_UNARY_OP_INVERT,
5252
MP_UNARY_OP_NOT,
53+
MP_UNARY_OP_SIZEOF, // for sys.getsizeof()
5354
} mp_unary_op_t;
5455

5556
typedef enum {

tests/unix/extra_coverage.py.exp

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ ame__
2525
__name__ path argv version
2626
version_info implementation platform byteorder
2727
maxsize exit stdin stdout
28-
stderr modules exc_info print_exception
28+
stderr modules exc_info getsizeof
29+
print_exception
2930
ementation
3031
# attrtuple
3132
(start=1, stop=2, step=3)

unix/mpconfigport_coverage.h

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define MICROPY_PY_DELATTR_SETATTR (1)
3838
#define MICROPY_PY_BUILTINS_HELP (1)
3939
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
40+
#define MICROPY_PY_SYS_GETSIZEOF (1)
4041
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
4142
#define MICROPY_PY_IO_BUFFEREDWRITER (1)
4243
#undef MICROPY_VFS_FAT

0 commit comments

Comments
 (0)