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);
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;
}
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
static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
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;
}
static void emit_write_byte_code_byte_uint(emit_t* emit, byte b1, uint num) {
if (num <= 127) { // fits in 0x7f
// fit argument in single byte
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_uint(emit_t* emit, byte b, uint num) {
emit_write_byte_code_byte(emit, b);
emit_write_byte_code_uint(emit, num);
}
static void emit_write_byte_code_byte_qstr(emit_t* emit, byte b1, qstr qstr) {
emit_write_byte_code_byte_uint(emit, b1, qstr);
/* currently unused
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
@ -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) {
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_pre(emit, 0);
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"));
}
mp_obj_t full_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
uint use_def_args = self->n_args - n_args;
mp_map_t *old_globals = rt_globals_get();
if (self->globals == old_globals) {
return mp_execute_byte_code(self->bytecode, args, n_args, self->n_state);
} else {
rt_globals_set(self->globals);
mp_obj_t result = mp_execute_byte_code(self->bytecode, args, n_args, self->n_state);
rt_globals_set(old_globals);
return result;
}
rt_globals_set(self->globals);
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);
rt_globals_set(old_globals);
return result;
}
const mp_obj_type_t fun_bc_type = {

10
py/vm.c
View File

@ -46,7 +46,7 @@ typedef enum {
#define TOP() (*sp)
#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
mp_obj_t temp_state[10];
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;
// init args
for (int i = 0; i < n_args; i++) {
assert(i < 8);
for (uint i = 0; i < n_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;
@ -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--) {
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]);
} else {
state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);