Skip to content

Commit 6d403eb

Browse files
committed
py/emitnative: Simplify layout and loading of native function prelude.
Now native functions and native generators have similar behaviour: the first machine-word of their code is an index to get to the prelude. This simplifies the handling of these types of functions, and also reduces the size of the emitted native machine code by no longer requiring special code at the start of the function to load a pointer to the prelude. Signed-off-by: Damien George <damien@micropython.org>
1 parent 9400229 commit 6d403eb

File tree

5 files changed

+38
-26
lines changed

5 files changed

+38
-26
lines changed

py/bc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,9 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw
336336
// On entry code_state should be allocated somewhere (stack/heap) and
337337
// contain the following valid entries:
338338
// - code_state->fun_bc should contain a pointer to the function object
339-
// - code_state->ip should contain a pointer to the beginning of the prelude
340339
// - code_state->n_state should be the number of objects in the local state
341340
void mp_setup_code_state_native(mp_code_state_native_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {
341+
code_state->ip = mp_obj_fun_native_get_prelude_ptr(code_state->fun_bc);
342342
code_state->sp = &code_state->state[0] - 1;
343343
mp_setup_code_state_helper((mp_code_state_t *)code_state, n_args, n_kw, args);
344344
}

py/emitnative.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,6 @@ struct _emit_t {
253253
int pass;
254254

255255
bool do_viper_types;
256-
bool prelude_offset_uses_u16_encoding;
257256

258257
mp_uint_t local_vtype_alloc;
259258
vtype_kind_t *local_vtype;
@@ -519,8 +518,11 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
519518
// work out size of state (locals plus stack)
520519
emit->n_state = scope->num_locals + scope->stack_size;
521520

521+
// Store in the first machine-word an index used to the function's prelude.
522+
// This is used at runtime by mp_obj_fun_native_get_prelude_ptr().
523+
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index);
524+
522525
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
523-
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index);
524526
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset);
525527
ASM_ENTRY(emit->as, emit->code_state_start);
526528

@@ -576,15 +578,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
576578
// Set code_state.fun_bc
577579
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
578580

579-
// Set code_state.ip, a pointer to the beginning of the prelude. This pointer is found
580-
// either directly in mp_obj_fun_bc_t.child_table (if there are no children), or in
581-
// mp_obj_fun_bc_t.child_table[num_children] (if num_children > 0).
582-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CHILD_TABLE);
583-
if (emit->prelude_ptr_index != 0) {
584-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, emit->prelude_ptr_index);
585-
}
586-
emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_PARENT_ARG_1);
587-
588581
// Set code_state.n_state (only works on little endian targets due to n_state being uint16_t)
589582
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_N_STATE, emit->n_state, REG_ARG_1);
590583

py/objfun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_
401401
STATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
402402
MP_STACK_CHECK();
403403
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
404-
mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void *)self->bytecode);
404+
mp_call_fun_t fun = mp_obj_fun_native_get_function_start(self);
405405
return fun(self_in, n_args, n_kw, args);
406406
}
407407

py/objfun.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,34 @@ static inline mp_obj_t mp_obj_new_fun_viper(const void *fun_data, const mp_modul
6969
return MP_OBJ_FROM_PTR(o);
7070
}
7171

72+
static inline const uint8_t *mp_obj_fun_native_get_prelude_ptr(const mp_obj_fun_bc_t *fun_native) {
73+
// Obtain a pointer to the start of the function prelude, based on prelude_ptr_index.
74+
uintptr_t prelude_ptr_index = ((uintptr_t *)fun_native->bytecode)[0];
75+
const uint8_t *prelude_ptr;
76+
if (prelude_ptr_index == 0) {
77+
prelude_ptr = (const uint8_t *)fun_native->child_table;
78+
} else {
79+
prelude_ptr = (const uint8_t *)fun_native->child_table[prelude_ptr_index];
80+
}
81+
return prelude_ptr;
82+
}
83+
84+
static inline void *mp_obj_fun_native_get_function_start(const mp_obj_fun_bc_t *fun_native) {
85+
// Obtain a pointer to the start of the function executable machine code.
86+
return MICROPY_MAKE_POINTER_CALLABLE((void *)(fun_native->bytecode + sizeof(uintptr_t)));
87+
}
88+
89+
static inline void *mp_obj_fun_native_get_generator_start(const mp_obj_fun_bc_t *fun_native) {
90+
// Obtain a pointer to the start of the generator executable machine code.
91+
uintptr_t start_offset = ((uintptr_t *)fun_native->bytecode)[1];
92+
return MICROPY_MAKE_POINTER_CALLABLE((void *)(fun_native->bytecode + start_offset));
93+
}
94+
95+
static inline void *mp_obj_fun_native_get_generator_resume(const mp_obj_fun_bc_t *fun_native) {
96+
// Obtain a pointer to the resume location of the generator executable machine code.
97+
return MICROPY_MAKE_POINTER_CALLABLE((void *)&((uintptr_t *)fun_native->bytecode)[2]);
98+
}
99+
72100
#endif
73101

74102
#if MICROPY_EMIT_INLINE_ASM

py/objgenerator.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k
101101
mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in);
102102

103103
// Determine start of prelude.
104-
uintptr_t prelude_ptr_index = ((uintptr_t *)self_fun->bytecode)[0];
105-
const uint8_t *prelude_ptr;
106-
if (prelude_ptr_index == 0) {
107-
prelude_ptr = (void *)self_fun->child_table;
108-
} else {
109-
prelude_ptr = (void *)self_fun->child_table[prelude_ptr_index];
110-
}
104+
const uint8_t *prelude_ptr = mp_obj_fun_native_get_prelude_ptr(self_fun);
111105

112106
// Extract n_state from the prelude.
113107
const uint8_t *ip = prelude_ptr;
@@ -119,17 +113,14 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k
119113
// Parse the input arguments and set up the code state
120114
o->pend_exc = mp_const_none;
121115
o->code_state.fun_bc = self_fun;
122-
o->code_state.ip = prelude_ptr;
123116
o->code_state.n_state = n_state;
124-
o->code_state.sp = &o->code_state.state[0] - 1;
125117
mp_setup_code_state_native(&o->code_state, n_args, n_kw, args);
126118

127119
// Indicate we are a native function, which doesn't use this variable
128120
o->code_state.exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_SENTINEL;
129121

130122
// Prepare the generator instance for execution
131-
uintptr_t start_offset = ((uintptr_t *)self_fun->bytecode)[1];
132-
o->code_state.ip = MICROPY_MAKE_POINTER_CALLABLE((void *)(self_fun->bytecode + start_offset));
123+
o->code_state.ip = mp_obj_fun_native_get_generator_start(self_fun);
133124

134125
return MP_OBJ_FROM_PTR(o);
135126
}
@@ -208,9 +199,9 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
208199

209200
#if MICROPY_EMIT_NATIVE
210201
if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
211-
// A native generator, with entry point 2 words into the "bytecode" pointer
202+
// A native generator.
212203
typedef uintptr_t (*mp_fun_native_gen_t)(void *, mp_obj_t);
213-
mp_fun_native_gen_t fun = MICROPY_MAKE_POINTER_CALLABLE((const void *)(self->code_state.fun_bc->bytecode + 2 * sizeof(uintptr_t)));
204+
mp_fun_native_gen_t fun = mp_obj_fun_native_get_generator_resume(self->code_state.fun_bc);
214205
ret_kind = fun((void *)&self->code_state, throw_value);
215206
} else
216207
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy