py: mp_execute_byte_code has 2 arg arrays, for more efficient default params.

This commit is contained in:
Damien George 2014-02-01 18:29:40 +00:00
parent 87413a4d0c
commit fb083ea986
4 changed files with 46 additions and 46 deletions

View File

@ -1,3 +1,3 @@
mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state); mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, uint n_state);
bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out); bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);
void mp_byte_code_print(const byte *code, int len); void mp_byte_code_print(const byte *code, int len);

View File

@ -107,6 +107,22 @@ static void emit_write_byte_code_byte_byte(emit_t* emit, byte b1, uint b2) {
c[1] = b2; c[1] = b2;
} }
static void emit_write_byte_code_uint(emit_t* emit, uint num) {
if (num <= 127) { // fits in 0x7f
// fit argument in single byte
byte* c = emit_get_cur_to_write_byte_code(emit, 1);
c[0] = num;
} else if (num <= 16383) { // fits in 0x3fff
// fit argument in two bytes
byte* c = emit_get_cur_to_write_byte_code(emit, 2);
c[0] = (num >> 8) | 0x80;
c[1] = num;
} else {
// larger numbers not implemented/supported
assert(0);
}
}
// integers (for small ints) are stored as 24 bits, in excess // integers (for small ints) are stored as 24 bits, in excess
static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) { static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
num += 0x800000; num += 0x800000;
@ -118,26 +134,21 @@ static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t n
c[3] = num >> 16; c[3] = num >> 16;
} }
static void emit_write_byte_code_byte_uint(emit_t* emit, byte b1, uint num) { static void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
if (num <= 127) { // fits in 0x7f emit_write_byte_code_byte(emit, b);
// fit argument in single byte emit_write_byte_code_uint(emit, num);
byte* c = emit_get_cur_to_write_byte_code(emit, 2);
c[0] = b1;
c[1] = num;
} else if (num <= 16383) { // fits in 0x3fff
// fit argument in two bytes
byte* c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = (num >> 8) | 0x80;
c[2] = num;
} else {
// larger numbers not implemented/supported
assert(0);
}
} }
static void emit_write_byte_code_byte_qstr(emit_t* emit, byte b1, qstr qstr) { /* currently unused
emit_write_byte_code_byte_uint(emit, b1, qstr); static void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) {
emit_write_byte_code_byte(emit, b);
emit_write_byte_code_byte_uint(emit, num1);
emit_write_byte_code_byte_uint(emit, num2);
}
*/
static void emit_write_byte_code_byte_qstr(emit_t* emit, byte b, qstr qstr) {
emit_write_byte_code_byte_uint(emit, b, qstr);
} }
// unsigned labels are relative to ip following this instruction, stored as 16 bits // unsigned labels are relative to ip following this instruction, stored as 16 bits
@ -665,13 +676,13 @@ static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) { static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
assert(n_dict_params == 0); assert(n_dict_params == 0);
if (n_default_params != 0) { if (n_default_params == 0) {
emit_pre(emit, 1);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
} else {
emit_bc_build_tuple(emit, n_default_params); emit_bc_build_tuple(emit, n_default_params);
emit_pre(emit, 0); emit_pre(emit, 0);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id); emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
} else {
emit_pre(emit, 1);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
} }
} }

View File

@ -154,26 +154,13 @@ mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *a
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments"));
} }
mp_obj_t full_args[n_args]; uint use_def_args = self->n_args - n_args;
if (n_args < self->n_args) {
memcpy(full_args, args, n_args * sizeof(*args));
int use_def_args = self->n_args - n_args;
memcpy(full_args + n_args, self->def_args + self->n_def_args - use_def_args, use_def_args * sizeof(*args));
args = full_args;
n_args = self->n_args;
}
// optimisation: allow the compiler to optimise this tail call for
// the common case when the globals don't need to be changed
mp_map_t *old_globals = rt_globals_get(); mp_map_t *old_globals = rt_globals_get();
if (self->globals == old_globals) { rt_globals_set(self->globals);
return mp_execute_byte_code(self->bytecode, args, n_args, self->n_state); mp_obj_t result = mp_execute_byte_code(self->bytecode, args, n_args, self->def_args + self->n_def_args - use_def_args, use_def_args, self->n_state);
} else { rt_globals_set(old_globals);
rt_globals_set(self->globals);
mp_obj_t result = mp_execute_byte_code(self->bytecode, args, n_args, self->n_state); return result;
rt_globals_set(old_globals);
return result;
}
} }
const mp_obj_type_t fun_bc_type = { const mp_obj_type_t fun_bc_type = {

10
py/vm.c
View File

@ -46,7 +46,7 @@ typedef enum {
#define TOP() (*sp) #define TOP() (*sp)
#define SET_TOP(val) *sp = (val) #define SET_TOP(val) *sp = (val)
mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state) { mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, uint n_state) {
// allocate state for locals and stack // allocate state for locals and stack
mp_obj_t temp_state[10]; mp_obj_t temp_state[10];
mp_obj_t *state = &temp_state[0]; mp_obj_t *state = &temp_state[0];
@ -56,10 +56,12 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
mp_obj_t *sp = &state[0] - 1; mp_obj_t *sp = &state[0] - 1;
// init args // init args
for (int i = 0; i < n_args; i++) { for (uint i = 0; i < n_args; i++) {
assert(i < 8);
state[n_state - 1 - i] = args[i]; state[n_state - 1 - i] = args[i];
} }
for (uint i = 0; i < n_args2; i++) {
state[n_state - 1 - n_args - i] = args2[i];
}
const byte *ip = code; const byte *ip = code;
@ -71,7 +73,7 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
{ {
for (uint n_local = *ip++; n_local > 0; n_local--) { for (uint n_local = *ip++; n_local > 0; n_local--) {
uint local_num = *ip++; uint local_num = *ip++;
if (local_num < n_args) { if (local_num < n_args + n_args2) {
state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]); state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
} else { } else {
state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL); state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);