add PK_LOW_MEMORY_MODE

This commit is contained in:
blueloveTH 2024-12-31 13:34:37 +08:00
parent 4cf9199c72
commit 93ca8d88f3
5 changed files with 67 additions and 16 deletions

View File

@ -8,6 +8,11 @@
/*************** feature settings ***************/ /*************** feature settings ***************/
// Reduce the startup memory usage for embedded systems
#ifndef PK_LOW_MEMORY_MODE // can be overridden by cmake
#define PK_LOW_MEMORY_MODE 0
#endif
// Whether to compile os-related modules or not // Whether to compile os-related modules or not
#ifndef PK_ENABLE_OS // can be overridden by cmake #ifndef PK_ENABLE_OS // can be overridden by cmake
#define PK_ENABLE_OS 1 #define PK_ENABLE_OS 1
@ -15,7 +20,11 @@
// GC min threshold // GC min threshold
#ifndef PK_GC_MIN_THRESHOLD // can be overridden by cmake #ifndef PK_GC_MIN_THRESHOLD // can be overridden by cmake
#define PK_GC_MIN_THRESHOLD 16384 #if PK_LOW_MEMORY_MODE
#define PK_GC_MIN_THRESHOLD 2048
#else
#define PK_GC_MIN_THRESHOLD 16384
#endif
#endif #endif
// Memory allocation functions // Memory allocation functions
@ -28,7 +37,11 @@
// This is the maximum size of the value stack in py_TValue units // This is the maximum size of the value stack in py_TValue units
// The actual size in bytes equals `sizeof(py_TValue) * PK_VM_STACK_SIZE` // The actual size in bytes equals `sizeof(py_TValue) * PK_VM_STACK_SIZE`
#ifndef PK_VM_STACK_SIZE // can be overridden by cmake #ifndef PK_VM_STACK_SIZE // can be overridden by cmake
#define PK_VM_STACK_SIZE 16384 #if PK_LOW_MEMORY_MODE
#define PK_VM_STACK_SIZE 2048
#else
#define PK_VM_STACK_SIZE 16384
#endif
#endif #endif
// This is the maximum number of local variables in a function // This is the maximum number of local variables in a function
@ -51,4 +64,4 @@
#define PK_PLATFORM_SEP '\\' #define PK_PLATFORM_SEP '\\'
#else #else
#define PK_PLATFORM_SEP '/' #define PK_PLATFORM_SEP '/'
#endif #endif

View File

@ -11,11 +11,10 @@ py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co,
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co); NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
typedef struct ValueStack { typedef struct ValueStack {
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
// true`.
py_TValue* sp; py_TValue* sp;
py_TValue* end; py_TValue* end;
py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128]; // We allocate extra places to keep `_sp` valid to detect stack overflow
py_TValue begin[PK_VM_STACK_SIZE + PK_MAX_CO_VARNAMES * 2];
} ValueStack; } ValueStack;
void ValueStack__ctor(ValueStack* self); void ValueStack__ctor(ValueStack* self);

View File

@ -100,6 +100,7 @@ void c11_sbuf__write_quoted(c11_sbuf* self, c11_sv sv, char quote) {
case '\b': c11_sbuf__write_cstrn(self, "\\b", 2); break; case '\b': c11_sbuf__write_cstrn(self, "\\b", 2); break;
default: { default: {
int u8bytes = c11__u8_header(c, true); int u8bytes = c11__u8_header(c, true);
if(i + u8bytes > sv.size) u8bytes = 0; // invalid utf8
if(u8bytes <= 1) { if(u8bytes <= 1) {
// not a valid utf8 char, or ascii // not a valid utf8 char, or ascii
if(!isprint(c)) { if(!isprint(c)) {

View File

@ -13,6 +13,14 @@ static bool stack_format_object(VM* self, c11_sv spec);
#define CHECK_RETURN_FROM_EXCEPT_OR_FINALLY() \ #define CHECK_RETURN_FROM_EXCEPT_OR_FINALLY() \
if(self->is_curr_exc_handled) py_clearexc(NULL) if(self->is_curr_exc_handled) py_clearexc(NULL)
#define CHECK_STACK_OVERFLOW() \
do { \
if(self->stack.sp > self->stack.end) { \
py_exception(tp_StackOverflowError, ""); \
goto __ERROR; \
} \
} while(0)
#define DISPATCH() \ #define DISPATCH() \
do { \ do { \
frame->ip++; \ frame->ip++; \
@ -92,7 +100,7 @@ FrameResult VM__run_top_frame(VM* self) {
pk_print_stack(self, frame, byte); pk_print_stack(self, frame, byte);
#endif #endif
if(self->is_signal_interrupted){ if(self->is_signal_interrupted) {
self->is_signal_interrupted = false; self->is_signal_interrupted = false;
py_exception(tp_KeyboardInterrupt, ""); py_exception(tp_KeyboardInterrupt, "");
goto __ERROR; goto __ERROR;
@ -132,15 +140,40 @@ FrameResult VM__run_top_frame(VM* self) {
POP(); POP();
DISPATCH(); DISPATCH();
/*****************************************/ /*****************************************/
case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH(); case OP_LOAD_CONST: {
case OP_LOAD_NONE: py_newnone(SP()++); DISPATCH(); CHECK_STACK_OVERFLOW();
case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH(); PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg));
case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH(); DISPATCH();
}
case OP_LOAD_NONE: {
CHECK_STACK_OVERFLOW();
py_newnone(SP()++);
DISPATCH();
}
case OP_LOAD_TRUE: {
CHECK_STACK_OVERFLOW();
py_newbool(SP()++, true);
DISPATCH();
}
case OP_LOAD_FALSE: {
CHECK_STACK_OVERFLOW();
py_newbool(SP()++, false);
DISPATCH();
}
/*****************************************/ /*****************************************/
case OP_LOAD_SMALL_INT: py_newint(SP()++, (int16_t)byte.arg); DISPATCH(); case OP_LOAD_SMALL_INT: {
CHECK_STACK_OVERFLOW();
py_newint(SP()++, (int16_t)byte.arg);
DISPATCH();
}
/*****************************************/ /*****************************************/
case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH(); case OP_LOAD_ELLIPSIS: {
CHECK_STACK_OVERFLOW();
py_newellipsis(SP()++);
DISPATCH();
}
case OP_LOAD_FUNCTION: { case OP_LOAD_FUNCTION: {
CHECK_STACK_OVERFLOW();
FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg); FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function)); Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
Function__ctor(ud, decl, frame->module); Function__ctor(ud, decl, frame->module);
@ -952,8 +985,12 @@ FrameResult VM__run_top_frame(VM* self) {
goto __ERROR; goto __ERROR;
} }
py_Type type = py_Type type = pk_newtype(py_name2str(name),
pk_newtype(py_name2str(name), base, frame->module, NULL, base_ti->is_python, false); base,
frame->module,
NULL,
base_ti->is_python,
false);
PUSH(py_tpobject(type)); PUSH(py_tpobject(type));
self->__curr_class = TOP(); self->__curr_class = TOP();
DISPATCH(); DISPATCH();

View File

@ -1,5 +1,6 @@
#include "pocketpy/interpreter/heap.h" #include "pocketpy/interpreter/heap.h"
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/config.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
void ManagedHeap__ctor(ManagedHeap* self, VM* vm) { void ManagedHeap__ctor(ManagedHeap* self, VM* vm) {
@ -94,7 +95,7 @@ PyObject* PyObject__new(py_Type type, int slots, int size) {
PyObject* self; PyObject* self;
// header + slots + udsize // header + slots + udsize
size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + size; size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + size;
if(size <= kPoolObjectBlockSize) { if(!PK_LOW_MEMORY_MODE && size <= kPoolObjectBlockSize) {
self = PoolObject_alloc(); self = PoolObject_alloc();
self->gc_is_large = false; self->gc_is_large = false;
} else { } else {