summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/compile.c8
-rw-r--r--py/emitnative.c93
-rw-r--r--py/emitnxtensawin.c1
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/objgenerator.c15
-rw-r--r--py/persistentcode.c24
6 files changed, 68 insertions, 79 deletions
diff --git a/py/compile.c b/py/compile.c
index 6bb601b92..2760d8bfb 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -3031,14 +3031,6 @@ STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
// they will be computed in this first pass
scope->stack_size = 0;
scope->exc_stack_size = 0;
-
- #if MICROPY_EMIT_NATIVE
- if (scope->emit_options == MP_EMIT_OPT_NATIVE_PYTHON || scope->emit_options == MP_EMIT_OPT_VIPER) {
- // allow native code to perfom basic tasks during the pass scope
- // note: the first argument passed here is mp_emit_common_t, not the native emitter context
- NATIVE_EMITTER_TABLE->start_pass((void *)&comp->emit_common, comp->pass, scope);
- }
- #endif
}
// compile
diff --git a/py/emitnative.c b/py/emitnative.c
index bfb37ef4f..ddc0b5b97 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -231,9 +231,7 @@ struct _emit_t {
exc_stack_entry_t *exc_stack;
int prelude_offset;
- #if N_PRELUDE_AS_BYTES_OBJ
- size_t prelude_const_table_offset;
- #endif
+ int prelude_ptr_index;
int start_offset;
int n_state;
uint16_t code_state_start;
@@ -349,16 +347,6 @@ STATIC void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) {
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
- if (pass == MP_PASS_SCOPE) {
- // Note: the first argument passed here is mp_emit_common_t, not the native emitter context
- #if N_PRELUDE_AS_BYTES_OBJ
- if (scope->emit_options == MP_EMIT_OPT_NATIVE_PYTHON) {
- mp_emit_common_alloc_const_obj((mp_emit_common_t *)emit, mp_const_none);
- }
- #endif
- return;
- }
-
emit->pass = pass;
emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER;
emit->stack_size = 0;
@@ -511,12 +499,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
emit->code_state_start = 0;
emit->stack_start = SIZEOF_CODE_STATE;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Load index of prelude bytes object in const_table
- mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_const_table_offset);
- #else
- mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_offset);
- #endif
+ mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index);
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset);
ASM_ENTRY(emit->as, SIZEOF_NLR_BUF);
@@ -562,41 +545,19 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
// Set code_state.fun_bc
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
- // Set code_state.ip, a pointer to the beginning of the prelude
+ // Set code_state.ip, a pointer to the beginning of the prelude. This pointer is found
+ // either directly in mp_obj_fun_bc_t.child_table (if there are no children), or in
+ // mp_obj_fun_bc_t.child_table[num_children] (if num_children > 0).
// Need to use some locals for this, so assert that they are available for use
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_1);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_2);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_3);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_4);
- int code_state_ip_local = emit->code_state_start + OFFSETOF_CODE_STATE_IP;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Prelude is a bytes object in const_table[prelude_const_table_offset].
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->prelude_const_table_offset);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, offsetof(mp_obj_str_t, data) / sizeof(uintptr_t));
- #else
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_1);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_2);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_3);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_4);
- // Prelude is at the end of the machine code
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_BYTECODE);
- if (emit->pass == MP_PASS_CODE_SIZE) {
- // Commit to the encoding size based on the value of prelude_offset in this pass.
- // By using 32768 as the cut-off it is highly unlikely that prelude_offset will
- // grow beyond 65535 by the end of thiss pass, and so require the larger encoding.
- emit->prelude_offset_uses_u16_encoding = emit->prelude_offset < 32768;
- }
- if (emit->prelude_offset_uses_u16_encoding) {
- assert(emit->prelude_offset <= 65535);
- ASM_MOV_REG_IMM_FIX_U16((emit)->as, REG_LOCAL_2, emit->prelude_offset);
- } else {
- ASM_MOV_REG_IMM_FIX_WORD((emit)->as, REG_LOCAL_2, emit->prelude_offset);
+ ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CHILD_TABLE);
+ if (emit->prelude_ptr_index != 0) {
+ ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->prelude_ptr_index);
}
- ASM_ADD_REG_REG(emit->as, REG_LOCAL_3, REG_LOCAL_2);
- #endif
- emit_native_mov_state_reg(emit, code_state_ip_local, REG_LOCAL_3);
+ emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_LOCAL_3);
// Set code_state.n_state (only works on little endian targets due to n_state being uint16_t)
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_N_STATE, emit->n_state, REG_ARG_1);
@@ -657,6 +618,7 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
if (!emit->do_viper_types) {
emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
+ emit->prelude_ptr_index = emit->emit_common->ct_cur_child;
size_t n_state = emit->n_state;
size_t n_exc_stack = 0; // exc-stack not needed for native code
@@ -693,16 +655,6 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
}
emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Create the prelude as a bytes object, and store it in the constant table
- mp_obj_t prelude = mp_const_none;
- if (emit->pass == MP_PASS_EMIT) {
- void *buf = emit->as->base.code_base + emit->prelude_offset;
- size_t n = emit->as->base.code_offset - emit->prelude_offset;
- prelude = mp_obj_new_bytes(buf, n);
- }
- emit->prelude_const_table_offset = mp_emit_common_alloc_const_obj(emit->emit_common, prelude);
- #endif
}
ASM_END_PASS(emit->as);
@@ -725,10 +677,33 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
void *f = mp_asm_base_get_code(&emit->as->base);
mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base);
+ mp_raw_code_t **children = emit->emit_common->children;
+ if (!emit->do_viper_types) {
+ #if MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE
+ // Executable code cannot be accessed byte-wise on this architecture, so copy
+ // the prelude to a separate memory region that is byte-wise readable.
+ void *buf = emit->as->base.code_base + emit->prelude_offset;
+ size_t n = emit->as->base.code_offset - emit->prelude_offset;
+ const uint8_t *prelude_ptr = memcpy(m_new(uint8_t, n), buf, n);
+ #else
+ // Point to the prelude directly, at the end of the machine code data.
+ const uint8_t *prelude_ptr = (const uint8_t *)f + emit->prelude_offset;
+ #endif
+
+ // Store the pointer to the prelude using the child_table.
+ assert(emit->prelude_ptr_index == emit->emit_common->ct_cur_child);
+ if (emit->prelude_ptr_index == 0) {
+ children = (void *)prelude_ptr;
+ } else {
+ children = m_renew(mp_raw_code_t *, children, emit->prelude_ptr_index, emit->prelude_ptr_index + 1);
+ children[emit->prelude_ptr_index] = (void *)prelude_ptr;
+ }
+ }
+
mp_emit_glue_assign_native(emit->scope->raw_code,
emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY,
f, f_len,
- emit->emit_common->children,
+ children,
#if MICROPY_PERSISTENT_CODE_SAVE
emit->emit_common->ct_cur_child,
emit->prelude_offset,
diff --git a/py/emitnxtensawin.c b/py/emitnxtensawin.c
index 38d5db13e..99aac08dc 100644
--- a/py/emitnxtensawin.c
+++ b/py/emitnxtensawin.c
@@ -15,7 +15,6 @@
#define NLR_BUF_IDX_LOCAL_3 (2 + 6) // a6
#define N_NLR_SETJMP (1)
-#define N_PRELUDE_AS_BYTES_OBJ (1)
#define N_XTENSAWIN (1)
#define EXPORT_FUN(name) emit_native_xtensawin_##name
#include "py/emitnative.c"
diff --git a/py/mpconfig.h b/py/mpconfig.h
index f9894b497..59ab84cd4 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -394,8 +394,10 @@
// Convenience definition for whether any native emitter is enabled
#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN)
-// Select prelude-as-bytes-object for certain emitters
-#define MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ (MICROPY_EMIT_XTENSAWIN)
+// Some architectures cannot read byte-wise from executable memory. In this case
+// the prelude for a native function (which usually sits after the machine code)
+// must be separated and placed somewhere where it can be read byte-wise.
+#define MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE (MICROPY_EMIT_XTENSAWIN)
// Convenience definition for whether any inline assembler emitter is enabled
#define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA)
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 12fd81a8b..802fd45bb 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -98,14 +98,13 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k
mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in);
// Determine start of prelude.
- uintptr_t prelude_offset = ((uintptr_t *)self_fun->bytecode)[0];
- #if MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ
- // Prelude is in bytes object in const_table, at index prelude_offset
- mp_obj_str_t *prelude_bytes = MP_OBJ_TO_PTR(self_fun->context->constants.obj_table[prelude_offset]);
- const uint8_t *prelude_ptr = prelude_bytes->data;
- #else
- const uint8_t *prelude_ptr = self_fun->bytecode + prelude_offset;
- #endif
+ uintptr_t prelude_ptr_index = ((uintptr_t *)self_fun->bytecode)[0];
+ const uint8_t *prelude_ptr;
+ if (prelude_ptr_index == 0) {
+ prelude_ptr = (void *)self_fun->child_table;
+ } else {
+ prelude_ptr = (void *)self_fun->child_table[prelude_ptr_index];
+ }
// Extract n_state from the prelude.
const uint8_t *ip = prelude_ptr;
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 0b5da8077..e23c775d1 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -348,7 +348,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
// Load children if any.
if (has_children) {
n_children = read_uint(reader);
- children = m_new(mp_raw_code_t *, n_children);
+ children = m_new(mp_raw_code_t *, n_children + (kind == MP_CODE_NATIVE_PY));
for (size_t i = 0; i < n_children; ++i) {
children[i] = load_raw_code(reader);
}
@@ -372,6 +372,17 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
#if MICROPY_EMIT_MACHINE_CODE
} else {
+ const uint8_t *prelude_ptr;
+ #if MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE
+ if (kind == MP_CODE_NATIVE_PY) {
+ // Executable code cannot be accessed byte-wise on this architecture, so copy
+ // the prelude to a separate memory region that is byte-wise readable.
+ void *buf = fun_data + prelude_offset;
+ size_t n = fun_data_len - prelude_offset;
+ prelude_ptr = memcpy(m_new(uint8_t, n), buf, n);
+ }
+ #endif
+
// Relocate and commit code to executable address space
reloc_info_t ri = {reader, rodata, bss};
#if defined(MP_PLAT_COMMIT_EXEC)
@@ -395,6 +406,17 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
}
#endif
+ if (kind == MP_CODE_NATIVE_PY) {
+ #if !MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE
+ prelude_ptr = fun_data + prelude_offset;
+ #endif
+ if (n_children == 0) {
+ children = (void *)prelude_ptr;
+ } else {
+ children[n_children] = (void *)prelude_ptr;
+ }
+ }
+
// Assign native code to raw code object
mp_emit_glue_assign_native(rc, kind,
fun_data, fun_data_len,