Ver código fonte

small refactor

blueloveTH 3 meses atrás
pai
commit
bfe471dc12

+ 3 - 13
docs/modules/gc.md

@@ -3,18 +3,8 @@ icon: package
 label: gc
 ---
 
-### `gc.collect()`
+Garbage collection interface module.
 
-Invoke the garbage collector.
+#### Source code
 
-### `gc.enable()`
-
-Enable automatic garbage collection.
-
-### `gc.disable()`
-
-Disable automatic garbage collection.
-
-### `gc.isenabled()`
-
-Return `True` if automatic garbage collection is enabled, `False` otherwise.
+:::code source="../../include/typings/gc.pyi" :::

+ 3 - 5
docs/modules/json.md

@@ -3,11 +3,9 @@ icon: package
 label: json
 ---
 
-### `json.loads(data: str)`
+JSON serialization and deserialization module.
 
-Decode a JSON string into a python object.
+#### Source code
 
-### `json.dumps(obj, indent=0) -> str`
-
-Encode a python object into a JSON string.
+:::code source="../../include/typings/json.pyi" :::
 

+ 1 - 1
docs/retype.yml

@@ -3,7 +3,7 @@ output: .retype
 url: https://pocketpy.dev
 branding:
   title: pocketpy
-  label: v2.1.4
+  label: v2.1.5
   logo: "./static/logo.png"
 favicon: "./static/logo.png"
 meta:

+ 2 - 2
include/pocketpy/config.h

@@ -1,10 +1,10 @@
 #pragma once
 // clang-format off
 
-#define PK_VERSION				"2.1.4"
+#define PK_VERSION				"2.1.5"
 #define PK_VERSION_MAJOR            2
 #define PK_VERSION_MINOR            1
-#define PK_VERSION_PATCH            4
+#define PK_VERSION_PATCH            5
 
 /*************** feature settings ***************/
 #ifndef PK_ENABLE_OS                // can be overridden by cmake

+ 1 - 1
include/pocketpy/interpreter/heap.h

@@ -44,7 +44,7 @@ void ManagedHeap__dtor(ManagedHeap* self);
 ManagedHeapSwpetInfo* ManagedHeapSwpetInfo__new();
 void ManagedHeapSwpetInfo__delete(ManagedHeapSwpetInfo* self);
 
-void ManagedHeap__collect_if_needed(ManagedHeap* self);
+void ManagedHeap__collect_hint(ManagedHeap* self);
 int ManagedHeap__collect(ManagedHeap* self);
 int ManagedHeap__sweep(ManagedHeap* self, ManagedHeapSwpetInfo* out_info);
 

+ 1 - 1
include/pocketpy/interpreter/objectpool.h

@@ -5,7 +5,7 @@
 
 #define kPoolArenaSize (120 * 1024)
 #define kMultiPoolCount 5
-#define kPoolMaxBlockSize (32 * kMultiPoolCount)
+// #define kPoolMaxBlockSize (32 * kMultiPoolCount)
 
 typedef struct PoolArena {
     int block_size;

+ 27 - 0
include/typings/gc.pyi

@@ -0,0 +1,27 @@
+from typing import Callable
+
+def isenabled() -> bool:
+    """Check if automatic garbage collection is enabled."""
+
+def enable() -> None:
+    """Enable automatic garbage collection."""
+
+def disable() -> None:
+    """Disable automatic garbage collection."""
+
+def collect() -> int:
+    """Run a full collection immediately.
+
+    Returns an integer indicating the number of unreachable objects found.
+    """
+
+def collect_hint() -> None:
+    """Hint the garbage collector to run a collection.
+
+    The typical usage scenario for this function is in frame-driven games,
+    where `gc.disable()` is called at the start of the game,
+    and `gc.collect_hint()` is called at the end of each frame.
+    """
+
+def setup_debug_callback(cb: Callable[[str], None] | None) -> None:
+    """Setup a callback that will be triggered at the end of each collection."""

+ 6 - 1
include/typings/inspect.pyi

@@ -1 +1,6 @@
-def isgeneratorfunction(obj) -> bool: ...
+def isgeneratorfunction(obj) -> bool: ...
+
+def is_user_defined_type(t: type) -> bool:
+    """Check if a type is user-defined.
+    
+    This means the type was created by executing python `class` statement."""

+ 2 - 0
include/typings/json.pyi

@@ -0,0 +1,2 @@
+def loads(s: str): ...
+def dumps(obj, indent=0): ...

+ 1 - 5
include/typings/pkpy.pyi

@@ -1,4 +1,4 @@
-from typing import Self, Literal, Callable
+from typing import Self, Literal
 from vmath import vec2, vec2i
 
 class TValue[T]:
@@ -16,11 +16,7 @@ configmacros: dict[str, int]
 
 def memory_usage() -> str:
     """Return a summary of the memory usage."""
-def setup_gc_debug_callback(cb: Callable[[str], None]) -> None:
-    """Setup a callback that will be triggered at the end of GC."""
 
-def is_user_defined_type(t: type) -> bool:
-    """Check if a type is user-defined. This means the type was created by executing python `class` statement."""
 
 def currentvm() -> int:
     """Return the current VM index."""

+ 1 - 1
src/interpreter/ceval.c

@@ -729,7 +729,7 @@ __NEXT_STEP:
         }
         /*****************************************/
         case OP_CALL: {
-            ManagedHeap__collect_if_needed(&self->heap);
+            if(self->heap.gc_enabled) ManagedHeap__collect_hint(&self->heap);
             vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
             DISPATCH();
         }

+ 3 - 7
src/interpreter/heap.c

@@ -94,8 +94,7 @@ static void ManagedHeap__fire_debug_callback(ManagedHeap* self, ManagedHeapSwpet
     }
 }
 
-void ManagedHeap__collect_if_needed(ManagedHeap* self) {
-    if(!self->gc_enabled) return;
+void ManagedHeap__collect_hint(ManagedHeap* self) {
     if(self->gc_counter < self->gc_threshold) return;
     self->gc_counter = 0;
 
@@ -185,13 +184,10 @@ int ManagedHeap__sweep(ManagedHeap* self, ManagedHeapSwpetInfo* out_info) {
 
 PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize) {
     assert(slots >= 0 || slots == -1);
-    PyObject* obj;
     // header + slots + udsize
     int size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + udsize;
-    if(size <= kPoolMaxBlockSize) {
-        obj = MultiPool__alloc(&self->small_objects, size);
-        assert(obj != NULL);
-    } else {
+    PyObject* obj = MultiPool__alloc(&self->small_objects, size);
+    if(obj == NULL) {
         obj = PK_MALLOC(size);
         c11_vector__push(PyObject*, &self->large_objects, obj);
     }

+ 1 - 1
src/interpreter/objectpool.c

@@ -141,7 +141,7 @@ static int Pool__sweep_dealloc(Pool* self,
 }
 
 void* MultiPool__alloc(MultiPool* self, int size) {
-    if(size == 0) return NULL;
+    assert(size > 0);
     int index = (size - 1) >> 5;
     if(index < kMultiPoolCount) {
         Pool* pool = &self->pools[index];

+ 28 - 9
src/modules/gc.c

@@ -1,14 +1,6 @@
 #include "pocketpy/pocketpy.h"
 #include "pocketpy/interpreter/vm.h"
 
-static bool gc_collect(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(0);
-    ManagedHeap* heap = &pk_current_vm->heap;
-    int res = ManagedHeap__collect(heap);
-    py_newint(py_retval(), res);
-    return true;
-}
-
 static bool gc_enable(int argc, py_Ref argv) {
     PY_CHECK_ARGC(0);
     ManagedHeap* heap = &pk_current_vm->heap;
@@ -32,11 +24,38 @@ static bool gc_isenabled(int argc, py_Ref argv) {
     return true;
 }
 
+static bool gc_collect(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(0);
+    ManagedHeap* heap = &pk_current_vm->heap;
+    int res = ManagedHeap__collect(heap);
+    py_newint(py_retval(), res);
+    return true;
+}
+
+static bool gc_collect_hint(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(0);
+    ManagedHeap* heap = &pk_current_vm->heap;
+    ManagedHeap__collect_hint(heap);
+    py_newnone(py_retval());
+    return true;
+}
+
+static bool gc_setup_debug_callback(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(1);
+    ManagedHeap* heap = &pk_current_vm->heap;
+    heap->debug_callback = *argv;
+    py_newnone(py_retval());
+    return true;
+}
+
 void pk__add_module_gc() {
     py_Ref mod = py_newmodule("gc");
 
-    py_bindfunc(mod, "collect", gc_collect);
     py_bindfunc(mod, "enable", gc_enable);
     py_bindfunc(mod, "disable", gc_disable);
     py_bindfunc(mod, "isenabled", gc_isenabled);
+
+    py_bindfunc(mod, "collect", gc_collect);
+    py_bindfunc(mod, "collect_hint", gc_collect_hint);
+    py_bindfunc(mod, "setup_debug_callback", gc_setup_debug_callback);
 }

+ 10 - 4
src/modules/inspect.c

@@ -1,8 +1,5 @@
 #include "pocketpy/pocketpy.h"
-
-#include "pocketpy/common/utils.h"
 #include "pocketpy/objects/object.h"
-#include "pocketpy/common/sstream.h"
 #include "pocketpy/interpreter/vm.h"
 
 static bool inspect_isgeneratorfunction(int argc, py_Ref argv) {
@@ -21,8 +18,17 @@ static bool inspect_isgeneratorfunction(int argc, py_Ref argv) {
     return true;
 }
 
+static bool inspect_is_user_defined_type(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(1);
+    PY_CHECK_ARG_TYPE(0, tp_type);
+    py_TypeInfo* ti = py_touserdata(argv);
+    py_newbool(py_retval(), ti->is_python);
+    return true;
+}
+
 void pk__add_module_inspect() {
     py_Ref mod = py_newmodule("inspect");
 
     py_bindfunc(mod, "isgeneratorfunction", inspect_isgeneratorfunction);
-}
+    py_bindfunc(mod, "is_user_defined_type", inspect_is_user_defined_type);
+}

+ 0 - 18
src/modules/pkpy.c

@@ -57,22 +57,6 @@ static bool pkpy_memory_usage(int argc, py_Ref argv) {
     return true;
 }
 
-static bool pkpy_setup_gc_debug_callback(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(1);
-    ManagedHeap* heap = &pk_current_vm->heap;
-    heap->debug_callback = *argv;
-    py_newnone(py_retval());
-    return true;
-}
-
-static bool pkpy_is_user_defined_type(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(1);
-    PY_CHECK_ARG_TYPE(0, tp_type);
-    py_TypeInfo* ti = py_touserdata(argv);
-    py_newbool(py_retval(), ti->is_python);
-    return true;
-}
-
 static bool pkpy_currentvm(int argc, py_Ref argv) {
     PY_CHECK_ARGC(0);
     py_newint(py_retval(), py_currentvm());
@@ -538,8 +522,6 @@ void pk__add_module_pkpy() {
     py_pop();
 
     py_bindfunc(mod, "memory_usage", pkpy_memory_usage);
-    py_bindfunc(mod, "setup_gc_debug_callback", pkpy_setup_gc_debug_callback);
-    py_bindfunc(mod, "is_user_defined_type", pkpy_is_user_defined_type);
 
     py_bindfunc(mod, "currentvm", pkpy_currentvm);
 

+ 1 - 2
tests/71_gc.py

@@ -1,7 +1,6 @@
 import gc
-from pkpy import setup_gc_debug_callback
 
-setup_gc_debug_callback(print)
+gc.setup_debug_callback(print)
 
 gc.collect()
 def create_garbage():

+ 1 - 1
tests/92_pkpy.py

@@ -1,4 +1,4 @@
-from pkpy import is_user_defined_type
+from inspect import is_user_defined_type
 
 class A:
     pass