Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
2039757b
Commit
2039757b
authored
Mar 28, 2015
by
Paul Sokolovsky
Browse files
vm: Initial support for calling bytecode functions w/o C stack ("stackless").
parent
f88eec0d
Changes
5
Show whitespace changes
Inline
Side-by-side
py/bc.c
View file @
2039757b
...
...
@@ -86,6 +86,9 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
mp_obj_fun_bc_t
*
self
=
self_in
;
mp_uint_t
n_state
=
code_state
->
n_state
;
#if MICROPY_STACKLESS
code_state
->
prev
=
NULL
;
#endif
code_state
->
code_info
=
self
->
bytecode
;
code_state
->
sp
=
&
code_state
->
state
[
0
]
-
1
;
code_state
->
exc_sp
=
(
mp_exc_stack_t
*
)(
code_state
->
state
+
n_state
)
-
1
;
...
...
py/bc.h
View file @
2039757b
...
...
@@ -46,6 +46,9 @@ typedef struct _mp_code_state {
// bit 0 is saved currently_in_except_block value
mp_exc_stack_t
*
exc_sp
;
mp_obj_dict_t
*
old_globals
;
#if MICROPY_STACKLESS
struct
_mp_code_state
*
prev
;
#endif
mp_uint_t
n_state
;
// Variable-length
mp_obj_t
state
[
0
];
...
...
@@ -56,6 +59,7 @@ typedef struct _mp_code_state {
mp_uint_t
mp_decode_uint
(
const
byte
**
ptr
);
mp_vm_return_kind_t
mp_execute_bytecode
(
mp_code_state
*
code_state
,
volatile
mp_obj_t
inject_exc
);
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
);
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
);
void
mp_bytecode_print
(
const
void
*
descr
,
mp_uint_t
n_total_args
,
const
byte
*
code
,
mp_uint_t
len
);
void
mp_bytecode_print2
(
const
byte
*
code
,
mp_uint_t
len
);
...
...
py/mpconfig.h
View file @
2039757b
...
...
@@ -125,6 +125,11 @@
#define MICROPY_QSTR_BYTES_IN_LEN (1)
#endif
// Avoid using C stack when making Python function calls.
#ifndef MICROPY_STACKLESS
#define MICROPY_STACKLESS (0)
#endif
/*****************************************************************************/
/* Micro Python emitters */
...
...
py/objfun.c
View file @
2039757b
...
...
@@ -142,6 +142,38 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
// Set this to enable a simple stack overflow check.
#define VM_DETECT_STACK_OVERFLOW (0)
mp_code_state
*
mp_obj_fun_bc_prepare_codestate
(
mp_obj_t
self_in
,
mp_uint_t
n_args
,
mp_uint_t
n_kw
,
const
mp_obj_t
*
args
)
{
MP_STACK_CHECK
();
mp_obj_fun_bc_t
*
self
=
self_in
;
// skip code-info block
const
byte
*
code_info
=
self
->
bytecode
;
mp_uint_t
code_info_size
=
mp_decode_uint
(
&
code_info
);
const
byte
*
ip
=
self
->
bytecode
+
code_info_size
;
// bytecode prelude: skip arg names
ip
+=
(
self
->
n_pos_args
+
self
->
n_kwonly_args
)
*
sizeof
(
mp_obj_t
);
// bytecode prelude: state size and exception stack size
mp_uint_t
n_state
=
mp_decode_uint
(
&
ip
);
mp_uint_t
n_exc_stack
=
mp_decode_uint
(
&
ip
);
// allocate state for locals and stack
mp_uint_t
state_size
=
n_state
*
sizeof
(
mp_obj_t
)
+
n_exc_stack
*
sizeof
(
mp_exc_stack_t
);
mp_code_state
*
code_state
;
code_state
=
m_new_obj_var
(
mp_code_state
,
byte
,
state_size
);
code_state
->
n_state
=
n_state
;
code_state
->
ip
=
ip
;
mp_setup_code_state
(
code_state
,
self_in
,
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
;
}
STATIC
mp_obj_t
fun_bc_call
(
mp_obj_t
self_in
,
mp_uint_t
n_args
,
mp_uint_t
n_kw
,
const
mp_obj_t
*
args
)
{
MP_STACK_CHECK
();
...
...
py/vm.c
View file @
2039757b
...
...
@@ -129,9 +129,12 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
// loop and the exception handler, leading to very obscure bugs.
#define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
#if MICROPY_STACKLESS
run_code_state:
;
#endif
// Pointers which are constant for particular invocation of mp_execute_bytecode()
mp_obj_t
*
const
fastn
=
&
code_state
->
state
[
code_state
->
n_state
-
1
];
mp_exc_stack_t
*
const
exc_stack
=
(
mp_exc_stack_t
*
)(
code_state
->
state
+
code_state
->
n_state
);
mp_obj_t
*/
*
const
*/
fastn
=
&
code_state
->
state
[
code_state
->
n_state
-
1
];
mp_exc_stack_t
*/
*
const
*/
exc_stack
=
(
mp_exc_stack_t
*
)(
code_state
->
state
+
code_state
->
n_state
);
// variables that are visible to the exception handler (declared volatile)
volatile
bool
currently_in_except_block
=
MP_TAGPTR_TAG0
(
code_state
->
exc_sp
);
// 0 or 1, to detect nested exceptions
...
...
@@ -865,6 +868,18 @@ unwind_jump:;
// unum & 0xff == n_positional
// (unum >> 8) & 0xff == n_keyword
sp
-=
(
unum
&
0xff
)
+
((
unum
>>
7
)
&
0x1fe
);
#if MICROPY_STACKLESS
if
(
mp_obj_get_type
(
*
sp
)
==
&
mp_type_fun_bc
)
{
code_state
->
ip
=
ip
;
code_state
->
sp
=
sp
;
code_state
->
exc_sp
=
MP_TAGPTR_MAKE
(
exc_sp
,
currently_in_except_block
);
mp_code_state
*
new_state
=
mp_obj_fun_bc_prepare_codestate
(
*
sp
,
unum
&
0xff
,
(
unum
>>
8
)
&
0xff
,
sp
+
1
);
new_state
->
prev
=
code_state
;
code_state
=
new_state
;
nlr_pop
();
goto
run_code_state
;
}
#endif
SET_TOP
(
mp_call_function_n_kw
(
*
sp
,
unum
&
0xff
,
(
unum
>>
8
)
&
0xff
,
sp
+
1
));
DISPATCH
();
}
...
...
@@ -925,6 +940,15 @@ unwind_return:
nlr_pop
();
code_state
->
sp
=
sp
;
assert
(
exc_sp
==
exc_stack
-
1
);
#if MICROPY_STACKLESS
if
(
code_state
->
prev
!=
NULL
)
{
mp_obj_t
res
=
*
sp
;
mp_globals_set
(
code_state
->
old_globals
);
code_state
=
code_state
->
prev
;
*
code_state
->
sp
=
res
;
goto
run_code_state
;
}
#endif
return
MP_VM_RETURN_NORMAL
;
ENTRY
(
MP_BC_RAISE_VARARGS
)
:
{
...
...
@@ -1122,6 +1146,9 @@ exception_handler:
goto
outer_dispatch_loop
;
// continue with dispatch loop
}
#if MICROPY_STACKLESS
unwind_loop:
#endif
// set file and line number that the exception occurred at
// TODO: don't set traceback for exceptions re-raised by END_FINALLY.
// But consider how to handle nested exceptions.
...
...
@@ -1185,6 +1212,18 @@ exception_handler:
PUSH
(
mp_obj_get_type
(
nlr
.
ret_val
));
code_state
->
sp
=
sp
;
#if MICROPY_STACKLESS
}
else
if
(
code_state
->
prev
!=
NULL
)
{
mp_globals_set
(
code_state
->
old_globals
);
code_state
=
code_state
->
prev
;
fastn
=
&
code_state
->
state
[
code_state
->
n_state
-
1
];
exc_stack
=
(
mp_exc_stack_t
*
)(
code_state
->
state
+
code_state
->
n_state
);
// variables that are visible to the exception handler (declared volatile)
currently_in_except_block
=
MP_TAGPTR_TAG0
(
code_state
->
exc_sp
);
// 0 or 1, to detect nested exceptions
exc_sp
=
MP_TAGPTR_PTR
(
code_state
->
exc_sp
);
// stack grows up, exc_sp points to top of stack
goto
unwind_loop
;
#endif
}
else
{
// propagate exception to higher level
// TODO what to do about ip and sp? they don't really make sense at this point
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment