summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-03-23 16:36:08 +1100
committerDamien George <damien.p.george@gmail.com>2017-03-23 16:36:08 +1100
commit60656eaea41df16557fbbdb51d9b8fc2cf7662a1 (patch)
tree862e226a7e29408e84dd00b1644947654741cc85
parent507119f4d80cc70cc35249f97c9b0ee22b8965f4 (diff)
downloadmicropython-60656eaea41df16557fbbdb51d9b8fc2cf7662a1.tar.gz
micropython-60656eaea41df16557fbbdb51d9b8fc2cf7662a1.zip
py: Define and use MP_OBJ_ITER_BUF_NSLOTS to get size of stack iter buf.
It improves readability of code and reduces the chance to make a mistake. This patch also fixes a bug with nan-boxing builds by rounding up the calculation of the new NSLOTS variable, giving the correct number of slots (being 4) even if mp_obj_t is larger than the native machine size.
-rw-r--r--py/compile.c1
-rw-r--r--py/emitbc.c6
-rw-r--r--py/emitnative.c8
-rw-r--r--py/obj.h4
-rw-r--r--py/vm.c23
5 files changed, 24 insertions, 18 deletions
diff --git a/py/compile.c b/py/compile.c
index ca21d8294c..2fbc19cc39 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -3005,6 +3005,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
// There are 4 slots on the stack for the iterator, and the first one is
// NULL to indicate that the second one points to the iterator object.
if (scope->kind == SCOPE_GEN_EXPR) {
+ // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4
EMIT(load_null);
compile_load_id(comp, qstr_arg);
EMIT(load_null);
diff --git a/py/emitbc.c b/py/emitbc.c
index 0076c147e1..673cd405f9 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -735,7 +735,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
// need to pop the iterator if we are breaking out of a for loop
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
// also pop the iter_buf
- for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; ++i) {
+ for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) {
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
}
}
@@ -778,7 +778,7 @@ void mp_emit_bc_end_finally(emit_t *emit) {
}
void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
- emit_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1 : 0);
+ emit_bc_pre(emit, use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0);
emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);
}
@@ -788,7 +788,7 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
}
void mp_emit_bc_for_iter_end(emit_t *emit) {
- emit_bc_pre(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
+ emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);
}
void mp_emit_bc_pop_block(emit_t *emit) {
diff --git a/py/emitnative.c b/py/emitnative.c
index 4af68102b9..3ab001f8d0 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -1761,7 +1761,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
if (use_stack) {
- emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, MP_OBJ_ITER_BUF_NSLOTS);
emit_call(emit, MP_F_NATIVE_GETITER);
} else {
// mp_getiter will allocate the iter_buf on the heap
@@ -1773,8 +1773,8 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
emit_native_pre(emit);
- emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
- adjust_stack(emit, 4);
+ emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS);
+ adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS);
emit_call(emit, MP_F_NATIVE_ITERNEXT);
ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
@@ -1784,7 +1784,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
STATIC void emit_native_for_iter_end(emit_t *emit) {
// adjust stack counter (we get here from for_iter ending, which popped the value for us)
emit_native_pre(emit);
- adjust_stack(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
+ adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS);
emit_post(emit);
}
diff --git a/py/obj.h b/py/obj.h
index 93078b81e1..fc122c4905 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -422,6 +422,10 @@ typedef struct _mp_obj_iter_buf_t {
mp_obj_t buf[3];
} mp_obj_iter_buf_t;
+// The number of slots that an mp_obj_iter_buf_t needs on the Python value stack.
+// It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D).
+#define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t))
+
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
diff --git a/py/vm.c b/py/vm.c
index ed8b9ec4da..96029664a5 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -684,7 +684,7 @@ unwind_jump:;
if (unum != 0) {
// pop iter and iter_buf
sp--;
- sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
+ sp -= MP_OBJ_ITER_BUF_NSLOTS;
}
DISPATCH_WITH_PEND_EXC_CHECK();
}
@@ -729,19 +729,20 @@ unwind_jump:;
SET_TOP(mp_getiter(TOP(), NULL));
DISPATCH();
- // An iterator for a for-loop takes 4 slots on the stack. They are either
- // used to store the iterator object itself, or the first slot is NULL and
+ // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on
+ // the Python value stack. These slots are either used to store the
+ // iterator object itself, or the first slot is MP_OBJ_NULL and
// the second slot holds a reference to the iterator object.
ENTRY(MP_BC_GET_ITER_STACK): {
MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = TOP();
mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
- sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1;
+ sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
obj = mp_getiter(obj, iter_buf);
if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
// Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
- sp[-3] = MP_OBJ_NULL;
- sp[-2] = obj;
+ sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL;
+ sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;
}
DISPATCH();
}
@@ -751,14 +752,14 @@ unwind_jump:;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->sp = sp;
mp_obj_t obj;
- if (sp[-3] == MP_OBJ_NULL) {
- obj = sp[-2];
+ if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {
+ obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];
} else {
- obj = MP_OBJ_FROM_PTR(&sp[-3]);
+ obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);
}
mp_obj_t value = mp_iternext_allow_raise(obj);
if (value == MP_OBJ_STOP_ITERATION) {
- sp -= 4; // pop the exhausted iterator
+ sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
ip += ulab; // jump to after for-block
} else {
PUSH(value); // push the next iteration value
@@ -1334,7 +1335,7 @@ exception_handler:
const byte *ip = code_state->ip + 1;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->ip = ip + ulab; // jump to after for-block
- code_state->sp -= 4; // pop the exhausted iterator
+ code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
goto outer_dispatch_loop; // continue with dispatch loop
} else if (*code_state->ip == MP_BC_YIELD_FROM) {
// StopIteration inside yield from call means return a value of