예제 #1
0
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
    MP_STACK_CHECK();
    mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);

    // bytecode prelude: state size and exception stack size
    size_t n_state = mp_decode_uint_value(self->bytecode);
    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));

    // allocate state for locals and stack
    size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
    mp_code_state_t *code_state;
    code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
    if (!code_state) {
        return NULL;
    }

    code_state->fun_bc = self;
    code_state->ip = 0;
    mp_setup_code_state(code_state, n_args, n_kw, args);

    // execute the byte code with the correct globals context
    code_state->old_globals = mp_globals_get();
    mp_globals_set(self->globals);

    return code_state;
}
예제 #2
0
qstr mp_obj_code_get_name(const byte *code_info) {
    code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry
    #if MICROPY_PERSISTENT_CODE
    return code_info[0] | (code_info[1] << 8);
    #else
    return mp_decode_uint_value(code_info);
    #endif
}
예제 #3
0
qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
    const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in);
    #if MICROPY_EMIT_NATIVE
    if (fun->base.type == &mp_type_fun_native) {
        // TODO native functions don't have name stored
        return MP_QSTR_;
    }
    #endif

    const byte *bc = fun->bytecode;
    bc = mp_decode_uint_skip(bc); // skip n_state
    bc = mp_decode_uint_skip(bc); // skip n_exc_stack
    bc++; // skip scope_params
    bc++; // skip n_pos_args
    bc++; // skip n_kwonly_args
    bc++; // skip n_def_pos_args
    return mp_obj_code_get_name(bc);
}
예제 #4
0
STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
    // A generating function is just a bytecode function with type mp_type_gen_wrap
    mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in);

    // bytecode prelude: get state size and exception stack size
    size_t n_state = mp_decode_uint_value(self_fun->bytecode);
    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode));

    // allocate the generator object, with room for local stack and exception stack
    mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte,
        n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t));
    o->base.type = &mp_type_gen_instance;

    o->globals = self_fun->globals;
    o->code_state.fun_bc = self_fun;
    o->code_state.ip = 0;
    mp_setup_code_state(&o->code_state, n_args, n_kw, args);
    return MP_OBJ_FROM_PTR(o);
}
예제 #5
0
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
    MP_STACK_CHECK();

    DEBUG_printf("Input n_args: " UINT_FMT ", n_kw: " UINT_FMT "\n", n_args, n_kw);
    DEBUG_printf("Input pos args: ");
    dump_args(args, n_args);
    DEBUG_printf("Input kw args: ");
    dump_args(args + n_args, n_kw * 2);
    mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
    DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);

    // bytecode prelude: state size and exception stack size
    size_t n_state = mp_decode_uint_value(self->bytecode);
    size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode));

#if VM_DETECT_STACK_OVERFLOW
    n_state += 1;
#endif

    // allocate state for locals and stack
    size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
    mp_code_state_t *code_state = NULL;
    if (state_size > VM_MAX_STATE_ON_STACK) {
        code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
    }
    if (code_state == NULL) {
        code_state = alloca(sizeof(mp_code_state_t) + state_size);
        state_size = 0; // indicate that we allocated using alloca
    }

    code_state->fun_bc = self;
    code_state->ip = 0;
    mp_setup_code_state(code_state, n_args, n_kw, args);

    // execute the byte code with the correct globals context
    code_state->old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL);
    mp_globals_set(code_state->old_globals);

#if VM_DETECT_STACK_OVERFLOW
    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        if (code_state->sp < code_state->state) {
            printf("VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state);
            assert(0);
        }
    }
    // We can't check the case when an exception is returned in state[n_state - 1]
    // and there are no arguments, because in this case our detection slot may have
    // been overwritten by the returned exception (which is allowed).
    if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) {
        // Just check to see that we have at least 1 null object left in the state.
        bool overflow = true;
        for (size_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) {
            if (code_state->state[i] == MP_OBJ_NULL) {
                overflow = false;
                break;
            }
        }
        if (overflow) {
            printf("VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state);
            assert(0);
        }
    }
#endif

    mp_obj_t result;
    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        // return value is in *sp
        result = *code_state->sp;
    } else {
        // must be an exception because normal functions can't yield
        assert(vm_return_kind == MP_VM_RETURN_EXCEPTION);
        // return value is in fastn[0]==state[n_state - 1]
        result = code_state->state[n_state - 1];
    }

    // free the state if it was allocated on the heap
    if (state_size != 0) {
        m_del_var(mp_code_state_t, byte, state_size, code_state);
    }

    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        return result;
    } else { // MP_VM_RETURN_EXCEPTION
        nlr_raise(result);
    }
}