Skip to content

[proof of concept] Implement parts of the core in Python bytecode #5025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion py/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj);
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj);
//MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj);
extern const struct _mp_obj_fun_bc_t mp_builtin_sum_obj;
// Defined by a port, but declared here for simplicity
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);
Expand Down
102 changes: 102 additions & 0 deletions py/modbuiltins.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,106 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round);

#if 1

// Implement sum() in Python!
//
// def sum(iterable, start=0):
// for x in iterable:
// start += x
// return start

#include "py/bc0.h"
#include "py/runtime0.h"
#include "py/objfun.h"

extern const mp_obj_type_t mp_type_fun_native;

#if 1
// Implement sum in Python bytecode

STATIC const uint8_t mp_builtin_sum_bytecode[] = {
0x09, // n_state
0x00, // n_exc_stack
0x80, // scope_flags (special top-bit set for internal bytecode function)
0x02, // n_pos_args
0x00, // n_kwonly_args
0x01, // n_def_pos_args
0x03, // code_info_size
MP_QSTR_sum & 0xff, MP_QSTR_sum >> 8, // simple_name
0xff, // end-of-list-sentinel for cells

MP_BC_LOAD_FAST_MULTI,
MP_BC_GET_ITER_STACK,
MP_BC_FOR_ITER, 0x08, 0x00, // +8
MP_BC_STORE_FAST_MULTI + 2,
MP_BC_LOAD_FAST_MULTI + 1,
MP_BC_LOAD_FAST_MULTI + 2,
MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_INPLACE_ADD,
MP_BC_STORE_FAST_MULTI + 1,
MP_BC_JUMP, 0xf5, 0x7f, // -11
MP_BC_LOAD_FAST_MULTI + 1,
MP_BC_RETURN_VALUE,
};
const mp_obj_fun_bc_t mp_builtin_sum_obj = {
.base = { &mp_type_fun_bc },
.globals = NULL,
.bytecode = mp_builtin_sum_bytecode,
.const_table = NULL,
{ MP_OBJ_NEW_SMALL_INT(0) }, // default start value
};

#else
// Implement sum in Python native code

#if defined(__x86_64__)
STATIC const byte mp_builtin_sum_fun_data[159] __attribute__((section(".text,\"ax\",@progbits # "))) = {
0x55, 0x53, 0x41, 0x54, 0x41, 0x55, 0x48, 0x83, 0xec, 0x78, 0x4c, 0x8b, 0x6f, 0x18, 0x49, 0x8b,
0x6d, 0x10, 0x48, 0x89, 0x3c, 0x24, 0xbf, 0x92, 0x00, 0x00, 0x00, 0x48, 0x89, 0x7c, 0x24, 0x08,
0x48, 0x89, 0xe7, 0x48, 0x8b, 0x85, 0x70, 0x01, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x8b, 0x5c, 0x24,
0x68, 0x4c, 0x8b, 0x64, 0x24, 0x60, 0x4c, 0x8b, 0x6c, 0x24, 0x58, 0x48, 0x89, 0xdf, 0x48, 0x8d,
0x74, 0x24, 0x28, 0x48, 0x8b, 0x85, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x8d, 0x7c, 0x24,
0x28, 0x48, 0x8b, 0x85, 0xf8, 0x00, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x1c,
0x00, 0x00, 0x00, 0x49, 0x89, 0xc5, 0x4c, 0x89, 0xea, 0x4c, 0x89, 0xe6, 0xbf, 0x0e, 0x00, 0x00,
0x00, 0x48, 0x8b, 0x85, 0x90, 0x00, 0x00, 0x00, 0xff, 0xd0, 0x49, 0x89, 0xc4, 0xeb, 0xcd, 0x4c,
0x89, 0xe0, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x88, 0x41, 0x5d, 0x41, 0x5c, 0x5b,
0x5d, 0xc3,
0x80, 0x09, 0x00, 0x00, 0x02, 0x00, 0x01, 0x05,
MP_QSTR_sum & 0xff, MP_QSTR_sum >> 8,
MP_QSTR_sum_dot_py & 0xff, MP_QSTR_sum_dot_py >> 8,
0xff,
};
#elif defined(__thumb2__)
STATIC const byte mp_builtin_sum_fun_data[87] __attribute__((section(".text,\"ax\",%progbits @ "))) __attribute__ ((aligned (2))) = {
0xfe, 0xb5, 0x8c, 0xb0, 0xc6, 0x68, 0xb7, 0x68, 0x00, 0x90, 0x4a, 0x20, 0x01, 0x90, 0x00, 0xa8,
0xd7, 0xf8, 0xb8, 0x40, 0xa0, 0x47, 0x0d, 0x9c, 0x0c, 0x9d, 0x0b, 0x9e, 0x20, 0x46, 0x05, 0xa9,
0xbb, 0x6f, 0x98, 0x47, 0x05, 0xa8, 0xfb, 0x6f, 0x98, 0x47, 0x00, 0x28, 0x00, 0xf0, 0x08, 0x80,
0x06, 0x46, 0x32, 0x46, 0x29, 0x46, 0x0e, 0x20, 0xbb, 0x6c, 0x98, 0x47, 0x05, 0x46, 0xf1, 0xe7,
0x28, 0x46, 0x00, 0xf0, 0x00, 0xb8, 0x0c, 0xb0, 0xfe, 0xbd,
0x80, 0x09, 0x00, 0x00, 0x02, 0x00, 0x01, 0x05,
MP_QSTR_sum & 0xff, MP_QSTR_sum >> 8,
MP_QSTR_sum_dot_py & 0xff, MP_QSTR_sum_dot_py >> 8,
0xff,
};
#endif
STATIC const mp_rom_obj_t mp_builtin_sum_const_table[3] = {
MP_ROM_QSTR(MP_QSTR_iterable),
MP_ROM_QSTR(MP_QSTR_start),
mp_fun_table,
};
const mp_obj_fun_bc_t mp_builtin_sum_obj = {
.base = { &mp_type_fun_native },
.globals = NULL,
.bytecode = mp_builtin_sum_fun_data,
.const_table = (void*)mp_builtin_sum_const_table,
{ MP_OBJ_NEW_SMALL_INT(0) }, // default start value
};

#endif

#else
// Implement sum in C

STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
mp_obj_t value;
switch (n_args) {
Expand All @@ -537,6 +637,8 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);

#endif

STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args > 1) {
mp_raise_TypeError("must use keyword argument for key function");
Expand Down
4 changes: 2 additions & 2 deletions py/objfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ qstr mp_obj_code_get_name(const byte *code_info) {
}

#if MICROPY_EMIT_NATIVE
STATIC const mp_obj_type_t mp_type_fun_native;
const mp_obj_type_t mp_type_fun_native;
#endif

qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
Expand Down Expand Up @@ -406,7 +406,7 @@ STATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co
return fun(self_in, n_args, n_kw, args);
}

STATIC const mp_obj_type_t mp_type_fun_native = {
const mp_obj_type_t mp_type_fun_native = {
{ &mp_type_type },
.name = MP_QSTR_function,
.call = fun_native_call,
Expand Down
5 changes: 5 additions & 0 deletions py/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,10 @@ unwind_jump:;
const byte *ip = code_state->fun_bc->bytecode;
ip = mp_decode_uint_skip(ip); // skip n_state
ip = mp_decode_uint_skip(ip); // skip n_exc_stack
if (*ip & 0x80) {
// builtin bytecode, don't add traceback info
goto skip_traceback;
}
ip++; // skip scope_params
ip++; // skip n_pos_args
ip++; // skip n_kwonly_args
Expand Down Expand Up @@ -1407,6 +1411,7 @@ unwind_jump:;
}
}
mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
skip_traceback:;
}

while (exc_sp >= exc_stack && exc_sp->handler <= code_state->ip) {
Expand Down