Skip to content

Commit 713ea18

Browse files
committed
py: Add constant table to bytecode.
Contains just argument names at the moment but makes it easy to add arbitrary constants.
1 parent 3a3db4d commit 713ea18

12 files changed

Lines changed: 97 additions & 96 deletions

File tree

py/bc.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
9797
// ip comes in as an offset into bytecode, so turn it into a true pointer
9898
code_state->ip = self->bytecode + (mp_uint_t)code_state->ip;
9999

100+
// store pointer to constant table
101+
code_state->const_table = self->const_table;
102+
100103
#if MICROPY_STACKLESS
101104
code_state->prev = NULL;
102105
#endif
@@ -107,9 +110,6 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
107110
mp_uint_t n_kwonly_args = *code_state->ip++;
108111
mp_uint_t n_def_pos_args = *code_state->ip++;
109112

110-
// align ip
111-
code_state->ip = MP_ALIGN(code_state->ip, sizeof(mp_uint_t));
112-
113113
code_state->sp = &code_state->state[0] - 1;
114114
code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;
115115

@@ -168,7 +168,7 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
168168
}
169169

170170
// get pointer to arg_names array
171-
const mp_obj_t *arg_names = (const mp_obj_t*)code_state->ip;
171+
const mp_obj_t *arg_names = (const mp_obj_t*)code_state->const_table;
172172

173173
for (mp_uint_t i = 0; i < n_kw; i++) {
174174
mp_obj_t wanted_arg_name = kwargs[2 * i];
@@ -243,7 +243,6 @@ continue2:;
243243

244244
// get the ip and skip argument names
245245
const byte *ip = code_state->ip;
246-
ip += (n_pos_args + n_kwonly_args) * sizeof(mp_uint_t);
247246

248247
// store pointer to code_info and jump over it
249248
{

py/bc.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,26 @@
3838
// n_kwonly_args : byte number of keyword-only arguments this function takes
3939
// n_def_pos_args : byte number of default positional arguments
4040
//
41-
// <word alignment padding>
42-
//
43-
// argname0 : obj (qstr)
44-
// ... : obj (qstr)
45-
// argnameN : obj (qstr) N = num_pos_args + num_kwonly_args
46-
//
4741
// code_info_size : var uint | code_info_size counts bytes in this chunk
4842
// simple_name : var qstr |
4943
// source_file : var qstr |
5044
// <line number info> |
51-
// <word alignment padding> |
45+
// <word alignment padding> | only needed if bytecode contains pointers
5246
//
53-
// num_cells : byte number of locals that are cells
54-
// local_num0 : byte
55-
// ... : byte
56-
// local_numN : byte N = num_cells
47+
// local_num0 : byte |
48+
// ... : byte |
49+
// local_numN : byte | N = num_cells
50+
// 255 : byte | end of list sentinel
51+
// <bytecode> |
5752
//
58-
// <bytecode>
53+
//
54+
// constant table layout:
55+
//
56+
// argname0 : obj (qstr)
57+
// ... : obj (qstr)
58+
// argnameN : obj (qstr) N = num_pos_args + num_kwonly_args
59+
// const0 : obj
60+
// constN : obj
5961

6062
// Exception stack entry
6163
typedef struct _mp_exc_stack {
@@ -70,6 +72,7 @@ typedef struct _mp_exc_stack {
7072
typedef struct _mp_code_state {
7173
const byte *code_info;
7274
const byte *ip;
75+
const mp_uint_t *const_table;
7376
mp_obj_t *sp;
7477
// bit 0 is saved currently_in_except_block value
7578
mp_exc_stack_t *exc_sp;
@@ -89,7 +92,7 @@ mp_uint_t mp_decode_uint(const byte **ptr);
8992
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc);
9093
mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
9194
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
92-
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len);
95+
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);
9396
void mp_bytecode_print2(const byte *code, mp_uint_t len);
9497
const byte *mp_bytecode_print_str(const byte *ip);
9598
#define mp_bytecode_print_inst(code) mp_bytecode_print2(code, 1)

py/emitbc.c

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct _emit_t {
5656
mp_uint_t bytecode_offset;
5757
mp_uint_t bytecode_size;
5858
byte *code_base; // stores both byte code and code info
59+
mp_uint_t *const_table;
5960
// Accessed as mp_uint_t, so must be aligned as such
6061
byte dummy_data[DUMMY_DATA_SIZE];
6162
};
@@ -123,13 +124,6 @@ STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
123124
emit_write_uint(emit, emit_get_cur_to_write_code_info, qst);
124125
}
125126

126-
STATIC void emit_write_code_info_prealigned_ptr(emit_t* emit, void *ptr) {
127-
mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_code_info(emit, sizeof(mp_uint_t));
128-
// Verify thar c is already uint-aligned
129-
assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
130-
*c = (mp_uint_t)ptr;
131-
}
132-
133127
#if MICROPY_ENABLE_SOURCE_LINE
134128
STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) {
135129
assert(bytes_to_skip > 0 || lines_to_skip > 0);
@@ -301,37 +295,6 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
301295
emit_write_code_info_byte(emit, emit->scope->num_kwonly_args);
302296
emit_write_code_info_byte(emit, emit->scope->num_def_pos_args);
303297

304-
// Align code-info so that following pointers are aligned on a machine word.
305-
emit_align_code_info_to_machine_word(emit);
306-
307-
// Write argument names (needed to resolve positional args passed as
308-
// keywords). We store them as full word-sized objects for efficient access
309-
// in mp_setup_code_state this is the start of the prelude and is guaranteed
310-
// to be aligned on a word boundary.
311-
{
312-
// For a given argument position (indexed by i) we need to find the
313-
// corresponding id_info which is a parameter, as it has the correct
314-
// qstr name to use as the argument name. Note that it's not a simple
315-
// 1-1 mapping (ie i!=j in general) because of possible closed-over
316-
// variables. In the case that the argument i has no corresponding
317-
// parameter we use "*" as its name (since no argument can ever be named
318-
// "*"). We could use a blank qstr but "*" is better for debugging.
319-
// Note: there is some wasted RAM here for the case of storing a qstr
320-
// for each closed-over variable, and maybe there is a better way to do
321-
// it, but that would require changes to mp_setup_code_state.
322-
for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
323-
qstr qst = MP_QSTR__star_;
324-
for (int j = 0; j < scope->id_info_len; ++j) {
325-
id_info_t *id = &scope->id_info[j];
326-
if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
327-
qst = id->qst;
328-
break;
329-
}
330-
}
331-
emit_write_code_info_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(qst));
332-
}
333-
}
334-
335298
// Write size of the rest of the code info. We don't know how big this
336299
// variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes
337300
// for it and hope that is enough! TODO assert this or something.
@@ -354,6 +317,35 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
354317
}
355318
}
356319
emit_write_bytecode_byte(emit, 255); // end of list sentinel
320+
321+
if (pass == MP_PASS_EMIT) {
322+
// Write argument names (needed to resolve positional args passed as
323+
// keywords). We store them as full word-sized objects for efficient access
324+
// in mp_setup_code_state this is the start of the prelude and is guaranteed
325+
// to be aligned on a word boundary.
326+
327+
// For a given argument position (indexed by i) we need to find the
328+
// corresponding id_info which is a parameter, as it has the correct
329+
// qstr name to use as the argument name. Note that it's not a simple
330+
// 1-1 mapping (ie i!=j in general) because of possible closed-over
331+
// variables. In the case that the argument i has no corresponding
332+
// parameter we use "*" as its name (since no argument can ever be named
333+
// "*"). We could use a blank qstr but "*" is better for debugging.
334+
// Note: there is some wasted RAM here for the case of storing a qstr
335+
// for each closed-over variable, and maybe there is a better way to do
336+
// it, but that would require changes to mp_setup_code_state.
337+
for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
338+
qstr qst = MP_QSTR__star_;
339+
for (int j = 0; j < scope->id_info_len; ++j) {
340+
id_info_t *id = &scope->id_info[j];
341+
if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
342+
qst = id->qst;
343+
break;
344+
}
345+
}
346+
emit->const_table[i] = (mp_uint_t)MP_OBJ_NEW_QSTR(qst);
347+
}
348+
}
357349
}
358350

359351
void mp_emit_bc_end_pass(emit_t *emit) {
@@ -377,9 +369,12 @@ void mp_emit_bc_end_pass(emit_t *emit) {
377369
emit->bytecode_size = emit->bytecode_offset;
378370
emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
379371

372+
emit->const_table = m_new0(mp_uint_t, emit->scope->num_pos_args + emit->scope->num_kwonly_args);
373+
380374
} else if (emit->pass == MP_PASS_EMIT) {
381375
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
382-
emit->code_info_size + emit->bytecode_size, emit->scope->scope_flags);
376+
emit->code_info_size + emit->bytecode_size,
377+
emit->const_table, emit->scope->scope_flags);
383378
}
384379
}
385380

py/emitglue.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ struct _mp_raw_code_t {
5151
union {
5252
struct {
5353
const byte *code;
54+
const mp_uint_t *const_table;
5455
} u_byte;
5556
struct {
5657
void *fun_data;
58+
const mp_uint_t *const_table;
5759
mp_uint_t type_sig; // for viper, compressed as 2-bit types; ret is MSB, then arg0, arg1, etc
5860
} u_native;
5961
} data;
@@ -65,28 +67,30 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
6567
return rc;
6668
}
6769

68-
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t scope_flags) {
70+
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len, const mp_uint_t *const_table, mp_uint_t scope_flags) {
6971
rc->kind = MP_CODE_BYTECODE;
7072
rc->scope_flags = scope_flags;
7173
rc->data.u_byte.code = code;
74+
rc->data.u_byte.const_table = const_table;
7275

7376
#ifdef DEBUG_PRINT
7477
DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
7578
#endif
7679
#if MICROPY_DEBUG_PRINTERS
7780
if (mp_verbose_flag >= 2) {
78-
mp_bytecode_print(rc, code, len);
81+
mp_bytecode_print(rc, code, len, const_table);
7982
}
8083
#endif
8184
}
8285

8386
#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
84-
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
87+
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
8588
assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
8689
rc->kind = kind;
8790
rc->scope_flags = scope_flags;
8891
rc->n_pos_args = n_pos_args;
8992
rc->data.u_native.fun_data = fun_data;
93+
rc->data.u_native.const_table = const_table;
9094
rc->data.u_native.type_sig = type_sig;
9195

9296
#ifdef DEBUG_PRINT
@@ -125,11 +129,11 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
125129
switch (rc->kind) {
126130
case MP_CODE_BYTECODE:
127131
no_other_choice:
128-
fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.code);
132+
fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.code, rc->data.u_byte.const_table);
129133
break;
130134
#if MICROPY_EMIT_NATIVE
131135
case MP_CODE_NATIVE_PY:
132-
fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data);
136+
fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
133137
break;
134138
case MP_CODE_NATIVE_VIPER:
135139
fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);

py/emitglue.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ typedef struct _mp_raw_code_t mp_raw_code_t;
4343

4444
mp_raw_code_t *mp_emit_glue_new_raw_code(void);
4545

46-
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t scope_flags);
47-
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig);
46+
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len, const mp_uint_t *const_table, mp_uint_t scope_flags);
47+
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig);
4848

4949
mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
5050
mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args);

py/emitinlinethumb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
9090

9191
if (emit->pass == MP_PASS_EMIT) {
9292
void *f = asm_thumb_get_code(emit->as);
93-
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), emit->scope->num_pos_args, 0, 0);
93+
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), NULL, emit->scope->num_pos_args, 0, 0);
9494
}
9595
}
9696

py/emitnative.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ struct _emit_t {
567567
vtype_kind_t saved_stack_vtype;
568568

569569
int prelude_offset;
570+
int const_table_offset;
570571
int n_state;
571572
int stack_start;
572573
int stack_size;
@@ -828,7 +829,24 @@ STATIC void emit_native_end_pass(emit_t *emit) {
828829
ASM_DATA(emit->as, 1, emit->scope->num_pos_args);
829830
ASM_DATA(emit->as, 1, emit->scope->num_kwonly_args);
830831
ASM_DATA(emit->as, 1, emit->scope->num_def_pos_args);
832+
833+
// write code info (just contains block name and source file)
834+
ASM_DATA(emit->as, 1, 5);
835+
ASM_DATA(emit->as, 2, emit->scope->simple_name);
836+
ASM_DATA(emit->as, 2, emit->scope->source_file);
837+
838+
// bytecode prelude: initialise closed over variables
839+
for (int i = 0; i < emit->scope->id_info_len; i++) {
840+
id_info_t *id = &emit->scope->id_info[i];
841+
if (id->kind == ID_INFO_KIND_CELL) {
842+
assert(id->local_num < 255);
843+
ASM_DATA(emit->as, 1, id->local_num); // write the local which should be converted to a cell
844+
}
845+
}
846+
ASM_DATA(emit->as, 1, 255); // end of list sentinel
847+
831848
ASM_ALIGN(emit->as, ASM_WORD_SIZE);
849+
emit->const_table_offset = ASM_GET_CODE_POS(emit->as);
832850

833851
// write argument names as qstr objects
834852
// see comment in corresponding part of emitbc.c about the logic here
@@ -844,18 +862,6 @@ STATIC void emit_native_end_pass(emit_t *emit) {
844862
ASM_DATA(emit->as, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
845863
}
846864

847-
// write dummy code info (for mp_setup_code_state to parse)
848-
ASM_DATA(emit->as, 1, 1);
849-
850-
// bytecode prelude: initialise closed over variables
851-
for (int i = 0; i < emit->scope->id_info_len; i++) {
852-
id_info_t *id = &emit->scope->id_info[i];
853-
if (id->kind == ID_INFO_KIND_CELL) {
854-
assert(id->local_num < 255);
855-
ASM_DATA(emit->as, 1, id->local_num); // write the local which should be converted to a cell
856-
}
857-
}
858-
ASM_DATA(emit->as, 1, 255); // end of list sentinel
859865
}
860866

861867
ASM_END_PASS(emit->as);
@@ -878,7 +884,8 @@ STATIC void emit_native_end_pass(emit_t *emit) {
878884

879885
mp_emit_glue_assign_native(emit->scope->raw_code,
880886
emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY,
881-
f, f_len, emit->scope->num_pos_args, emit->scope->scope_flags, type_sig);
887+
f, f_len, (mp_uint_t*)((byte*)f + emit->const_table_offset),
888+
emit->scope->num_pos_args, emit->scope->scope_flags, type_sig);
882889
}
883890
}
884891

py/obj.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,8 @@ mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg);
537537
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args);
538538
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);
539539
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
540-
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
541-
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data);
540+
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table);
541+
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table);
542542
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
543543
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data);
544544
mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);

py/objfun.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,9 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
126126
mp_decode_uint(&bc); // skip n_state
127127
mp_decode_uint(&bc); // skip n_exc_stack
128128
bc++; // skip scope_params
129-
mp_uint_t n_pos_args = *bc++;
130-
mp_uint_t n_kwonly_args = *bc++;
129+
bc++; // skip n_pos_args
130+
bc++; // skip n_kwonly_args
131131
bc++; // skip n_def_pos_args
132-
bc = MP_ALIGN(bc, sizeof(mp_uint_t)); // align
133-
bc += (n_pos_args + n_kwonly_args) * sizeof(mp_uint_t); // skip arg names
134132
return mp_obj_code_get_name(bc);
135133
}
136134

@@ -320,7 +318,7 @@ const mp_obj_type_t mp_type_fun_bc = {
320318
#endif
321319
};
322320

323-
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) {
321+
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) {
324322
mp_uint_t n_def_args = 0;
325323
mp_uint_t n_extra_args = 0;
326324
mp_obj_tuple_t *def_args = def_args_in;
@@ -336,6 +334,7 @@ mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byt
336334
o->base.type = &mp_type_fun_bc;
337335
o->globals = mp_globals_get();
338336
o->bytecode = code;
337+
o->const_table = const_table;
339338
if (def_args != MP_OBJ_NULL) {
340339
memcpy(o->extra_args, def_args->items, n_def_args * sizeof(mp_obj_t));
341340
}
@@ -364,8 +363,8 @@ STATIC const mp_obj_type_t mp_type_fun_native = {
364363
.unary_op = mp_generic_unary_op,
365364
};
366365

367-
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data) {
368-
mp_obj_fun_bc_t *o = mp_obj_new_fun_bc(def_args_in, def_kw_args, (const byte*)fun_data);
366+
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table) {
367+
mp_obj_fun_bc_t *o = mp_obj_new_fun_bc(def_args_in, def_kw_args, (const byte*)fun_data, const_table);
369368
o->base.type = &mp_type_fun_native;
370369
return o;
371370
}

0 commit comments

Comments
 (0)