Compare commits

..

9 Commits

Author SHA1 Message Date
blueloveTH
c0d5f1e575 add PK_ENABLE_CUSTOM_SNAME 2025-06-05 22:18:50 +08:00
blueloveTH
8fe2e4457f fix pybind 2025-06-05 22:07:40 +08:00
blueloveTH
6b80817a98 fix all 2025-06-05 21:18:47 +08:00
blueloveTH
785bb6841e fix all 2025-06-05 21:12:54 +08:00
blueloveTH
9281ebec56 revert ci 2025-06-05 20:07:09 +08:00
blueloveTH
6b592b11df fix all 2025-06-05 20:05:43 +08:00
blueloveTH
a21765a9ca backup 2025-06-05 19:57:14 +08:00
blueloveTH
59e60cf3c0 backup 2025-06-05 19:40:29 +08:00
blueloveTH
2404c6fe2b Update ceval.c 2025-06-05 18:18:52 +08:00
19 changed files with 82 additions and 53 deletions

View File

@ -2,7 +2,6 @@ name: build
on: on:
push: push:
branches: [ main ]
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
- 'web/**' - 'web/**'

View File

@ -2,7 +2,6 @@ name: PKBIND Build and Test
on: on:
push: push:
branches: [ main ]
paths-ignore: paths-ignore:
- "docs/**" - "docs/**"
- "web/**" - "web/**"

View File

@ -4,6 +4,8 @@
#include "http/HttpMessage.h" #include "http/HttpMessage.h"
#include "base/hplatform.h" #include "base/hplatform.h"
#include "pocketpy/common/name.h"
extern "C" void pk__add_module_libhv(); extern "C" void pk__add_module_libhv();
void libhv_HttpRequest_create(py_OutRef out, HttpRequestPtr ptr); void libhv_HttpRequest_create(py_OutRef out, HttpRequestPtr ptr);

View File

@ -53,6 +53,11 @@ if(PK_ENABLE_WATCHDOG)
add_definitions(-DPK_ENABLE_WATCHDOG=1) add_definitions(-DPK_ENABLE_WATCHDOG=1)
endif() endif()
if(PK_ENABLE_CUSTOM_SNAME)
add_definitions(-DPK_ENABLE_CUSTOM_SNAME=1)
endif()
if(PK_BUILD_MODULE_LZ4) if(PK_BUILD_MODULE_LZ4)
add_subdirectory(3rd/lz4) add_subdirectory(3rd/lz4)
add_definitions(-DPK_BUILD_MODULE_LZ4) add_definitions(-DPK_BUILD_MODULE_LZ4)

View File

@ -9,6 +9,7 @@ endif()
option(PK_ENABLE_OS "" OFF) option(PK_ENABLE_OS "" OFF)
option(PK_ENABLE_DETERMINISM "" OFF) option(PK_ENABLE_DETERMINISM "" OFF)
option(PK_ENABLE_WATCHDOG "" OFF) option(PK_ENABLE_WATCHDOG "" OFF)
option(PK_ENABLE_CUSTOM_SNAME "" OFF)
# modules # modules
option(PK_BUILD_MODULE_LZ4 "" OFF) option(PK_BUILD_MODULE_LZ4 "" OFF)

View File

@ -8,3 +8,8 @@ void pk_names_finalize();
#define MAGIC_METHOD(x) extern py_Name x; #define MAGIC_METHOD(x) extern py_Name x;
#include "pocketpy/xmacros/magics.h" #include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD #undef MAGIC_METHOD
py_Name py_namev(c11_sv name);
c11_sv py_name2sv(py_Name index);
py_Name py_name(const char* name);
const char* py_name2str(py_Name index);

View File

@ -20,6 +20,10 @@
#define PK_ENABLE_WATCHDOG 0 #define PK_ENABLE_WATCHDOG 0
#endif #endif
#ifndef PK_ENABLE_CUSTOM_SNAME // can be overridden by cmake
#define PK_ENABLE_CUSTOM_SNAME 0
#endif
// 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 32768 #define PK_GC_MIN_THRESHOLD 32768
@ -62,9 +66,9 @@
// Hash table load factor (smaller ones mean less collision but more memory) // Hash table load factor (smaller ones mean less collision but more memory)
// For class instance // For class instance
#define PK_INST_ATTR_LOAD_FACTOR 0.67 #define PK_INST_ATTR_LOAD_FACTOR 0.67f
// For class itself // For class itself
#define PK_TYPE_ATTR_LOAD_FACTOR 0.5 #define PK_TYPE_ATTR_LOAD_FACTOR 0.5f
#ifdef _WIN32 #ifdef _WIN32
#define PK_PLATFORM_SEP '\\' #define PK_PLATFORM_SEP '\\'

View File

@ -30,8 +30,8 @@ public:
auto& info = type_info::of<T>(); auto& info = type_info::of<T>();
info.name = name; info.name = name;
py_newfunction( py_bind(
py_tpgetmagic(this->index(), __new__), py_tpobject(this->index()),
"__new__(type, *args, **kwargs)", "__new__(type, *args, **kwargs)",
[](int, py_Ref stack) { [](int, py_Ref stack) {
auto cls = py_offset(stack, 0); auto cls = py_offset(stack, 0);
@ -44,9 +44,7 @@ public:
py_newobject(py_retval(), steal<type>(cls).index(), slot, sizeof(instance)); py_newobject(py_retval(), steal<type>(cls).index(), slot, sizeof(instance));
new (data) instance{instance::Flag::Own, operator new (info->size), info}; new (data) instance{instance::Flag::Own, operator new (info->size), info};
return true; return true;
}, });
nullptr,
0);
} }
/// bind constructor /// bind constructor

View File

@ -101,25 +101,25 @@ inline object::operator bool () const { return raise_call<py_bool>(m_ptr); }
return object::from_ret(); \ return object::from_ret(); \
} }
PKBIND_BINARY_OPERATOR(==, __eq__, __eq__) PKBIND_BINARY_OPERATOR(==, py_name("__eq__"), py_name("__eq__"))
PKBIND_BINARY_OPERATOR(!=, __ne__, __ne__) PKBIND_BINARY_OPERATOR(!=, py_name("__ne__"), py_name("__ne__"))
PKBIND_BINARY_OPERATOR(<, __lt__, __gt__) PKBIND_BINARY_OPERATOR(<, py_name("__lt__"), py_name("__gt__"))
PKBIND_BINARY_OPERATOR(<=, __le__, __ge__) PKBIND_BINARY_OPERATOR(<=, py_name("__le__"), py_name("__ge__"))
PKBIND_BINARY_OPERATOR(>, __gt__, __lt__) PKBIND_BINARY_OPERATOR(>, py_name("__gt__"), py_name("__lt__"))
PKBIND_BINARY_OPERATOR(>=, __ge__, __le__) PKBIND_BINARY_OPERATOR(>=, py_name("__ge__"), py_name("__le__"))
PKBIND_BINARY_OPERATOR(+, __add__, __radd__) PKBIND_BINARY_OPERATOR(+, py_name("__add__"), py_name("__radd__"))
PKBIND_BINARY_OPERATOR(-, __sub__, __rsub__) PKBIND_BINARY_OPERATOR(-, py_name("__sub__"), py_name("__rsub__"))
PKBIND_BINARY_OPERATOR(*, __mul__, __rmul__) PKBIND_BINARY_OPERATOR(*, py_name("__mul__"), py_name("__rmul__"))
PKBIND_BINARY_OPERATOR(/, __truediv__, __rtruediv__) PKBIND_BINARY_OPERATOR(/, py_name("__truediv__"), py_name("__rtruediv__"))
PKBIND_BINARY_OPERATOR(%, __mod__, __rmod__) PKBIND_BINARY_OPERATOR(%, py_name("__mod__"), py_name("__rmod__"))
// FIXME: support __rand__ ... // FIXME: support __rand__ ...
PKBIND_BINARY_OPERATOR(&, __and__, 0) PKBIND_BINARY_OPERATOR(&, py_name("__and__"), nullptr)
PKBIND_BINARY_OPERATOR(|, __or__, 0) PKBIND_BINARY_OPERATOR(|, py_name("__or__"), nullptr)
PKBIND_BINARY_OPERATOR(^, __xor__, 0) PKBIND_BINARY_OPERATOR(^, py_name("__xor__"), nullptr)
PKBIND_BINARY_OPERATOR(<<, __lshift__, 0) PKBIND_BINARY_OPERATOR(<<, py_name("__lshift__"), nullptr)
PKBIND_BINARY_OPERATOR(>>, __rshift__, 0) PKBIND_BINARY_OPERATOR(>>, py_name("__rshift__"), nullptr)
#undef PKBIND_BINARY_OPERATOR #undef PKBIND_BINARY_OPERATOR

View File

@ -1,3 +1,5 @@
#if PK_ENABLE_CUSTOM_SNAME == 0
#include "pocketpy/common/name.h" #include "pocketpy/common/name.h"
#include "pocketpy/common/str.h" #include "pocketpy/common/str.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
@ -14,7 +16,7 @@ typedef struct NameBucket {
static struct { static struct {
NameBucket* table[0x10000]; NameBucket* table[0x10000];
atomic_bool lock; atomic_flag lock;
} pk_string_table; } pk_string_table;
#define MAGIC_METHOD(x) py_Name x; #define MAGIC_METHOD(x) py_Name x;
@ -40,24 +42,25 @@ void pk_names_finalize() {
} }
py_Name py_namev(c11_sv name) { py_Name py_namev(c11_sv name) {
while(atomic_exchange(&pk_string_table.lock, true)) { while(atomic_flag_test_and_set(&pk_string_table.lock)) {
// busy-wait until the lock is released // busy-wait until the lock is released
} }
uint64_t hash = c11_sv__hash(name); uint64_t hash = c11_sv__hash(name);
int index = hash & 0xFFFF; int index = hash & 0xFFFF;
NameBucket* p = pk_string_table.table[index]; NameBucket* p = pk_string_table.table[index];
NameBucket* prev = NULL;
bool found = false; bool found = false;
while(p) { while(p) {
c11_sv p_sv = {p->data, p->size}; c11_sv p_sv = {p->data, p->size};
if(p->hash == hash && c11__sveq(p_sv, name)) { if(p->hash == hash && c11__sveq(p_sv, name)) {
found = true; found = true;
break; break;
} else {
p = p->next;
} }
prev = p;
p = p->next;
} }
if(found) { if(found) {
atomic_store(&pk_string_table.lock, false); atomic_flag_clear(&pk_string_table.lock);
return (py_Name)p; return (py_Name)p;
} }
@ -68,13 +71,13 @@ py_Name py_namev(c11_sv name) {
bucket->size = name.size; bucket->size = name.size;
memcpy(bucket->data, name.data, name.size); memcpy(bucket->data, name.data, name.size);
bucket->data[name.size] = '\0'; bucket->data[name.size] = '\0';
if(p == NULL) { if(prev == NULL) {
pk_string_table.table[index] = bucket; pk_string_table.table[index] = bucket;
} else { } else {
assert(p->next == NULL); assert(prev->next == NULL);
p->next = bucket; prev->next = bucket;
} }
atomic_store(&pk_string_table.lock, false); atomic_flag_clear(&pk_string_table.lock);
return (py_Name)bucket; return (py_Name)bucket;
} }
@ -94,3 +97,5 @@ const char* py_name2str(py_Name index) {
NameBucket* p = (NameBucket*)index; NameBucket* p = (NameBucket*)index;
return p->data; return p->data;
} }
#endif

View File

@ -92,6 +92,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_exception(tp_RecursionError, "maximum recursion depth exceeded"); py_exception(tp_RecursionError, "maximum recursion depth exceeded");
goto __ERROR; goto __ERROR;
} }
// NOTE: remember to change another occurrence after __ERROR_RE_RAISE:
co_codes = frame->co->codes.data; co_codes = frame->co->codes.data;
co_names = frame->co->names.data; co_names = frame->co->names.data;
frame->ip++; frame->ip++;
@ -901,7 +902,7 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_POP_IMPORT_STAR: { case OP_POP_IMPORT_STAR: {
// [module] // [module]
NameDict* dict = PyObject__dict(TOP()->_obj); NameDict* dict = PyObject__dict(TOP()->_obj);
py_Ref all = NameDict__try_get(dict, __all__); py_ItemRef all = NameDict__try_get(dict, __all__);
if(all) { if(all) {
py_TValue* p; py_TValue* p;
int length = pk_arrayview(all, &p); int length = pk_arrayview(all, &p);
@ -911,7 +912,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
for(int i = 0; i < length; i++) { for(int i = 0; i < length; i++) {
py_Name name = py_namev(py_tosv(p + i)); py_Name name = py_namev(py_tosv(p + i));
py_Ref value = NameDict__try_get(dict, name); py_ItemRef value = NameDict__try_get(dict, name);
if(value == NULL) { if(value == NULL) {
ImportError("cannot import name '%n'", name); ImportError("cannot import name '%n'", name);
goto __ERROR; goto __ERROR;
@ -920,7 +921,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
} }
} else { } else {
for(int i = 0; i < dict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
c11_sv name = py_name2sv(kv->key); c11_sv name = py_name2sv(kv->key);
@ -1239,6 +1240,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
frame = self->top_frame; frame = self->top_frame;
co_codes = frame->co->codes.data; co_codes = frame->co->codes.data;
co_names = frame->co->names.data;
goto __ERROR; goto __ERROR;
} }
} }

View File

@ -678,9 +678,9 @@ void ManagedHeap__mark(ManagedHeap* self) {
for(int i = 0; i < obj->slots; i++) for(int i = 0; i < obj->slots; i++)
pk__mark_value(p + i); pk__mark_value(p + i);
} else if(obj->slots == -1) { } else if(obj->slots == -1) {
NameDict* namedict = PyObject__dict(obj); NameDict* dict = PyObject__dict(obj);
for(int i = 0; i < namedict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &namedict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
pk__mark_value(&kv->value); pk__mark_value(&kv->value);
} }

View File

@ -84,7 +84,8 @@ static bool disassemble(CodeObject* co) {
case OP_BEGIN_CLASS: case OP_BEGIN_CLASS:
case OP_DELETE_GLOBAL: case OP_DELETE_GLOBAL:
case OP_STORE_CLASS_ATTR: { case OP_STORE_CLASS_ATTR: {
pk_sprintf(&ss, " (%n)", byte.arg); py_Name name = c11__getitem(py_Name, &co->names, byte.arg);
pk_sprintf(&ss, " (%n)", name);
break; break;
} }
case OP_LOAD_FAST: case OP_LOAD_FAST:

View File

@ -374,7 +374,7 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
} }
if(ti->is_python) { if(ti->is_python) {
NameDict* dict = PyObject__dict(obj->_obj); NameDict* dict = PyObject__dict(obj->_obj);
for(int i = dict->length - 1; i >= 0; i--) { for(int i = dict->capacity - 1; i >= 0; i--) {
NameDict_KV* kv = &dict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
if(!pkl__write_object(buf, &kv->value)) return false; if(!pkl__write_object(buf, &kv->value)) return false;
@ -383,7 +383,7 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
pkl__emit_int(buf, obj->type); pkl__emit_int(buf, obj->type);
buf->used_types[obj->type] = true; buf->used_types[obj->type] = true;
pkl__emit_int(buf, dict->length); pkl__emit_int(buf, dict->length);
for(int i = 0; i < dict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
c11_sv field = py_name2sv(kv->key); c11_sv field = py_name2sv(kv->key);

View File

@ -217,7 +217,8 @@ static bool ComputeThread__init__(int argc, py_Ref argv) {
static bool ComputeThread_is_done(int argc, py_Ref argv) { static bool ComputeThread_is_done(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_ComputeThread* self = py_touserdata(argv); c11_ComputeThread* self = py_touserdata(argv);
py_newbool(py_retval(), atomic_load(&self->is_done)); bool value = atomic_load(&self->is_done);
py_newbool(py_retval(), value);
return true; return true;
} }

View File

@ -764,9 +764,9 @@ void function__gc_mark(void* ud, c11_vector* p_stack) {
Function* func = ud; Function* func = ud;
if(func->globals) pk__mark_value(func->globals); if(func->globals) pk__mark_value(func->globals);
if(func->closure) { if(func->closure) {
NameDict* namedict = func->closure; NameDict* dict = func->closure;
for(int i = 0; i < namedict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &namedict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
pk__mark_value(&kv->value); pk__mark_value(&kv->value);
} }

View File

@ -225,6 +225,13 @@ char* py_formatexc() {
} }
bool py_exception(py_Type type, const char* fmt, ...) { bool py_exception(py_Type type, const char* fmt, ...) {
#ifndef NDEBUG
if(py_checkexc(true)) {
const char* name = py_tpname(pk_current_vm->curr_exception.type);
c11__abort("py_exception(): `%s` was already set!", name);
}
#endif
c11_sbuf buf; c11_sbuf buf;
c11_sbuf__ctor(&buf); c11_sbuf__ctor(&buf);
va_list args; va_list args;

View File

@ -52,11 +52,11 @@ static bool namedict_items(int argc, py_Ref argv) {
py_Ref object = py_getslot(argv, 0); py_Ref object = py_getslot(argv, 0);
NameDict* dict = PyObject__dict(object->_obj); NameDict* dict = PyObject__dict(object->_obj);
py_newlist(py_retval()); py_newlist(py_retval());
for(int i = 0; i < dict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
py_Ref slot = py_list_emplace(py_retval());
py_Ref p = py_newtuple(slot, 2);
NameDict_KV* kv = &dict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
py_Ref slot = py_list_emplace(py_retval());
py_Ref p = py_newtuple(slot, 2);
p[0] = *py_name2ref(kv->key); p[0] = *py_name2ref(kv->key);
p[1] = kv->value; p[1] = kv->value;
} }

View File

@ -26,7 +26,7 @@ py_ItemRef py_emplacedict(py_Ref self, py_Name name) {
bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) { bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
NameDict* dict = PyObject__dict(self->_obj); NameDict* dict = PyObject__dict(self->_obj);
for(int i = 0; i < dict->length; i++) { for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i]; NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue; if(kv->key == NULL) continue;
bool ok = f(kv->key, &kv->value, ctx); bool ok = f(kv->key, &kv->value, ctx);