Skip to content

Commit 20006db

Browse files
committed
Make VM stack grow upwards, and so no reversed args arrays.
Change state layout in VM so the stack starts at state[0] and grows upwards. Locals are at the top end of the state and number downwards. This cleans up a lot of the interface connecting the VM to C: now all functions that take an array of Micro Python objects are in order (ie no longer in reverse). Also clean up C API with keyword arguments (call_n and call_n_kw replaced with single call method that takes keyword arguments). And now make_new takes keyword arguments. emitnative.c has not yet been changed to comply with the new order of stack layout.
1 parent 8655065 commit 20006db

28 files changed

+325
-372
lines changed

py/builtin.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ static mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) {
4545
// TODO do proper metaclass resolution for multiple base objects
4646

4747
// create the new class using a call to the meta object
48-
// (arguments must be backwards in the array)
4948
mp_obj_t meta_args[3];
50-
meta_args[2] = args[1]; // class name
49+
meta_args[0] = args[1]; // class name
5150
meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases
52-
meta_args[0] = class_locals; // dict of members
53-
mp_obj_t new_class = rt_call_function_n(meta, 3, meta_args);
51+
meta_args[2] = class_locals; // dict of members
52+
mp_obj_t new_class = rt_call_function_n_kw(meta, 3, 0, meta_args);
5453

5554
// store into cell if neede
5655
if (cell != mp_const_none) {
@@ -153,10 +152,10 @@ static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
153152
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
154153
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
155154
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
156-
mp_obj_t revs_args[2];
157-
revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
158-
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
159-
return rt_build_tuple(2, revs_args);
155+
mp_obj_t args[2];
156+
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
157+
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
158+
return rt_build_tuple(2, args);
160159
} else {
161160
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
162161
}
@@ -327,20 +326,14 @@ static mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
327326

328327
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
329328

330-
static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) {
331-
mp_obj_t *args_items = NULL;
332-
uint args_len = 0;
333-
334-
assert(MP_OBJ_IS_TYPE(args, &tuple_type));
335-
mp_obj_tuple_get(args, &args_len, &args_items);
336-
assert(args_len >= 1);
337-
if (args_len > 1) {
329+
static mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
330+
assert(n_args >= 1);
331+
if (n_args > 1) {
338332
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
339333
"must use keyword argument for key function"));
340334
}
341-
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items);
342-
mp_obj_t new_args = rt_build_tuple(1, &self);
343-
mp_obj_list_sort(new_args, kwargs);
335+
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, 0, args);
336+
mp_obj_list_sort(1, &self, kwargs);
344337

345338
return self;
346339
}

py/emitnative.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,8 @@ static void emit_native_call_function(emit_t *emit, int n_positional, int n_keyw
11561156
vtype_kind_t vtype_fun;
11571157
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
11581158
assert(vtype_fun == VTYPE_PYOBJ);
1159-
emit_call_with_imm_arg(emit, RT_F_CALL_FUNCTION_N, rt_call_function_n, n_positional, REG_ARG_2);
1159+
// XXX rt_call_function_n now merged with rt_call_function_n_kw
1160+
//emit_call_with_imm_arg(emit, RT_F_CALL_FUNCTION_N, rt_call_function_n, n_positional, REG_ARG_2);
11601161
//}
11611162
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
11621163
}
@@ -1181,7 +1182,8 @@ static void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor
11811182
*/
11821183
emit_pre(emit);
11831184
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_positional + 2); // pointer to items in reverse order, including meth and self
1184-
emit_call_with_imm_arg(emit, RT_F_CALL_METHOD_N, rt_call_method_n, n_positional, REG_ARG_1);
1185+
// XXX rt_call_method_n now merged with rt_call_method_n_kw
1186+
//emit_call_with_imm_arg(emit, RT_F_CALL_METHOD_N, rt_call_method_n, n_positional, REG_ARG_1);
11851187
//}
11861188
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
11871189
}

py/obj.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
6363
return false;
6464
} else {
6565
mp_obj_base_t *o = o_in;
66-
return o->type->call_n != NULL;
66+
return o->type->call != NULL;
6767
}
6868
}
6969

py/obj.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,18 @@ typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t);
8383
typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);
8484
typedef mp_obj_t (*mp_fun_t)(void);
8585
typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *);
86-
typedef mp_obj_t (*mp_fun_kw_t)(mp_obj_t, struct _mp_map_t*);
86+
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, struct _mp_map_t *);
8787

8888
typedef enum {
8989
PRINT_STR, PRINT_REPR
9090
} mp_print_kind_t;
9191

9292
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
93-
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, int n_args, const mp_obj_t *args); // args are in reverse order in the array
94-
typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array
95-
typedef mp_obj_t (*mp_call_n_kw_fun_t)(mp_obj_t fun, int n_args, int n_kw, const mp_obj_t *args); // args are in reverse order in the array
93+
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
94+
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
9695
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
9796
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
98-
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[1] = value; for method, dest[0] = self, dest[1] = method
97+
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
9998
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded
10099

101100
typedef struct _mp_method_t {
@@ -144,8 +143,7 @@ struct _mp_obj_type_t {
144143
mp_print_fun_t print;
145144
mp_make_new_fun_t make_new; // to make an instance of the type
146145

147-
mp_call_n_fun_t call_n;
148-
mp_call_n_kw_fun_t call_n_kw;
146+
mp_call_fun_t call;
149147
mp_unary_op_fun_t unary_op; // can return NULL if op not supported
150148
mp_binary_op_fun_t binary_op; // can return NULL if op not supported
151149

@@ -222,13 +220,11 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun);
222220
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args);
223221
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple);
224222
mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items);
225-
mp_obj_t mp_obj_new_tuple_reverse(uint n, const mp_obj_t *items);
226223
mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items);
227-
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items);
228224
mp_obj_t mp_obj_new_dict(int n_args);
229225
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
230226
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
231-
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth);
227+
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
232228
mp_obj_t mp_obj_new_module(qstr module_name);
233229

234230
mp_obj_t mp_obj_get_type(mp_obj_t o_in);
@@ -296,7 +292,7 @@ extern const mp_obj_type_t list_type;
296292
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
297293
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
298294
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
299-
mp_obj_t mp_obj_list_sort(mp_obj_t args, struct _mp_map_t *kwargs);
295+
mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, struct _mp_map_t *kwargs);
300296

301297
// map (the python builtin, not the dict implementation detail)
302298
extern const mp_obj_type_t map_type;

py/objbool.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env
2222
}
2323
}
2424

25-
// args are reverse in the array
26-
static mp_obj_t bool_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
25+
static mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
26+
// TODO check n_kw == 0
27+
2728
switch (n_args) {
2829
case 0: return mp_const_false;
2930
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }

py/objboundmeth.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <stdlib.h>
2-
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <string.h>
34
#include <assert.h>
45

56
#include "nlr.h"
@@ -14,32 +15,36 @@ typedef struct _mp_obj_bound_meth_t {
1415
mp_obj_t self;
1516
} mp_obj_bound_meth_t;
1617

17-
// args are in reverse order in the array
18-
mp_obj_t bound_meth_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
18+
mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
1919
mp_obj_bound_meth_t *self = self_in;
2020

21-
if (n_args == 0) {
22-
return rt_call_function_n(self->meth, 1, &self->self);
23-
} else if (n_args == 1) {
24-
mp_obj_t args2[2];
25-
args2[1] = self->self;
26-
args2[0] = args[0];
27-
return rt_call_function_n(self->meth, 2, args2);
21+
// need to insert self->self before all other args and then call self->meth
22+
23+
int n_total = n_args + 2 * n_kw;
24+
if (n_total <= 4) {
25+
// use stack to allocate temporary args array
26+
mp_obj_t args2[5];
27+
args2[0] = self->self;
28+
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
29+
return rt_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
2830
} else {
29-
// TODO not implemented
30-
assert(0);
31-
return mp_const_none;
32-
//return rt_call_function_2(self->meth, n_args + 1, self->self + args);
31+
// use heap to allocate temporary args array
32+
mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_total);
33+
args2[0] = self->self;
34+
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
35+
mp_obj_t res = rt_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
36+
m_del(mp_obj_t, args2, 1 + n_total);
37+
return res;
3338
}
3439
}
3540

3641
const mp_obj_type_t bound_meth_type = {
3742
{ &mp_const_type },
3843
"bound_method",
39-
.call_n = bound_meth_call_n,
44+
.call = bound_meth_call,
4045
};
4146

42-
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth) {
47+
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {
4348
mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t);
4449
o->base.type = &bound_meth_type;
4550
o->meth = meth;

py/objclosure.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,33 @@ typedef struct _mp_obj_closure_t {
1616
mp_obj_t *closed;
1717
} mp_obj_closure_t;
1818

19-
// args are in reverse order in the array
20-
mp_obj_t closure_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
19+
mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
2120
mp_obj_closure_t *self = self_in;
2221

23-
// concatenate args and closed-over-vars, in reverse order
24-
// TODO perhaps cache this array so we don't need to create it each time we are called
25-
mp_obj_t *args2 = m_new(mp_obj_t, self->n_closed + n_args);
26-
memcpy(args2, args, n_args * sizeof(mp_obj_t));
27-
for (int i = 0; i < self->n_closed; i++) {
28-
args2[n_args + i] = self->closed[self->n_closed - 1 - i];
29-
}
22+
// need to concatenate closed-over-vars and args
3023

31-
// call the function with the new vars array
32-
return rt_call_function_n(self->fun, n_args + self->n_closed, args2);
24+
int n_total = self->n_closed + n_args + 2 * n_kw;
25+
if (n_total <= 5) {
26+
// use stack to allocate temporary args array
27+
mp_obj_t args2[5];
28+
memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));
29+
memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
30+
return rt_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);
31+
} else {
32+
// use heap to allocate temporary args array
33+
mp_obj_t *args2 = m_new(mp_obj_t, n_total);
34+
memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));
35+
memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
36+
mp_obj_t res = rt_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);
37+
m_del(mp_obj_t, args2, n_total);
38+
return res;
39+
}
3340
}
3441

3542
const mp_obj_type_t closure_type = {
3643
{ &mp_const_type },
3744
"closure",
38-
.call_n = closure_call_n,
45+
.call = closure_call,
3946
};
4047

4148
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) {

py/objcomplex.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp
3030
}
3131
}
3232

33-
// args are reverse in the array
34-
static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
33+
static mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
34+
// TODO check n_kw == 0
35+
3536
switch (n_args) {
3637
case 0:
3738
return mp_obj_new_complex(0, 0);
@@ -47,19 +48,19 @@ static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *a
4748
case 2:
4849
{
4950
mp_float_t real, imag;
50-
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
51-
mp_obj_complex_get(args[1], &real, &imag);
51+
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
52+
mp_obj_complex_get(args[0], &real, &imag);
5253
} else {
53-
real = mp_obj_get_float(args[1]);
54+
real = mp_obj_get_float(args[0]);
5455
imag = 0;
5556
}
56-
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
57+
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
5758
mp_float_t real2, imag2;
58-
mp_obj_complex_get(args[0], &real2, &imag2);
59+
mp_obj_complex_get(args[1], &real2, &imag2);
5960
real -= imag2;
6061
imag += real2;
6162
} else {
62-
imag += mp_obj_get_float(args[0]);
63+
imag += mp_obj_get_float(args[1]);
6364
}
6465
return mp_obj_new_complex(real, imag);
6566
}

py/objdict.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
3838
print(env, "}");
3939
}
4040

41-
// args are reverse in the array
42-
static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
41+
static mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
4342
// TODO create from an iterable!
4443
return rt_build_map(0);
4544
}

py/objenumerate.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,12 @@ static mp_obj_t enumerate_iternext(mp_obj_t self_in);
2020

2121
/* TODO: enumerate is one of the ones that can take args or kwargs.
2222
Sticking to args for now */
23-
static mp_obj_t enumerate_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
24-
/* NOTE: args are backwards */
23+
static mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
2524
assert(n_args > 0);
26-
args += n_args - 1;
2725
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
2826
o->base.type = &enumerate_type;
2927
o->iter = rt_getiter(args[0]);
30-
o->cur = n_args > 1 ? mp_obj_get_int(args[-1]) : 0;
31-
28+
o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;
3229
return o;
3330
}
3431

0 commit comments

Comments
 (0)