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:
push:
branches: [ main ]
paths-ignore:
- 'docs/**'
- 'web/**'

View File

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

View File

@ -4,6 +4,8 @@
#include "http/HttpMessage.h"
#include "base/hplatform.h"
#include "pocketpy/common/name.h"
extern "C" void pk__add_module_libhv();
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)
endif()
if(PK_ENABLE_CUSTOM_SNAME)
add_definitions(-DPK_ENABLE_CUSTOM_SNAME=1)
endif()
if(PK_BUILD_MODULE_LZ4)
add_subdirectory(3rd/lz4)
add_definitions(-DPK_BUILD_MODULE_LZ4)

View File

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

View File

@ -7,4 +7,9 @@ void pk_names_finalize();
#define MAGIC_METHOD(x) extern py_Name x;
#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
#endif
#ifndef PK_ENABLE_CUSTOM_SNAME // can be overridden by cmake
#define PK_ENABLE_CUSTOM_SNAME 0
#endif
// GC min threshold
#ifndef PK_GC_MIN_THRESHOLD // can be overridden by cmake
#define PK_GC_MIN_THRESHOLD 32768
@ -62,9 +66,9 @@
// Hash table load factor (smaller ones mean less collision but more memory)
// For class instance
#define PK_INST_ATTR_LOAD_FACTOR 0.67
#define PK_INST_ATTR_LOAD_FACTOR 0.67f
// For class itself
#define PK_TYPE_ATTR_LOAD_FACTOR 0.5
#define PK_TYPE_ATTR_LOAD_FACTOR 0.5f
#ifdef _WIN32
#define PK_PLATFORM_SEP '\\'

View File

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

View File

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

View File

@ -1,3 +1,5 @@
#if PK_ENABLE_CUSTOM_SNAME == 0
#include "pocketpy/common/name.h"
#include "pocketpy/common/str.h"
#include "pocketpy/pocketpy.h"
@ -14,7 +16,7 @@ typedef struct NameBucket {
static struct {
NameBucket* table[0x10000];
atomic_bool lock;
atomic_flag lock;
} pk_string_table;
#define MAGIC_METHOD(x) py_Name x;
@ -40,24 +42,25 @@ void pk_names_finalize() {
}
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
}
uint64_t hash = c11_sv__hash(name);
int index = hash & 0xFFFF;
NameBucket* p = pk_string_table.table[index];
NameBucket* prev = NULL;
bool found = false;
while(p) {
c11_sv p_sv = {p->data, p->size};
if(p->hash == hash && c11__sveq(p_sv, name)) {
found = true;
break;
} else {
p = p->next;
}
prev = p;
p = p->next;
}
if(found) {
atomic_store(&pk_string_table.lock, false);
atomic_flag_clear(&pk_string_table.lock);
return (py_Name)p;
}
@ -68,13 +71,13 @@ py_Name py_namev(c11_sv name) {
bucket->size = name.size;
memcpy(bucket->data, name.data, name.size);
bucket->data[name.size] = '\0';
if(p == NULL) {
if(prev == NULL) {
pk_string_table.table[index] = bucket;
} else {
assert(p->next == NULL);
p->next = bucket;
assert(prev->next == NULL);
prev->next = bucket;
}
atomic_store(&pk_string_table.lock, false);
atomic_flag_clear(&pk_string_table.lock);
return (py_Name)bucket;
}
@ -93,4 +96,6 @@ py_Name py_name(const char* name) {
const char* py_name2str(py_Name index) {
NameBucket* p = (NameBucket*)index;
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");
goto __ERROR;
}
// NOTE: remember to change another occurrence after __ERROR_RE_RAISE:
co_codes = frame->co->codes.data;
co_names = frame->co->names.data;
frame->ip++;
@ -901,7 +902,7 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_POP_IMPORT_STAR: {
// [module]
NameDict* dict = PyObject__dict(TOP()->_obj);
py_Ref all = NameDict__try_get(dict, __all__);
py_ItemRef all = NameDict__try_get(dict, __all__);
if(all) {
py_TValue* 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++) {
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) {
ImportError("cannot import name '%n'", name);
goto __ERROR;
@ -920,7 +921,7 @@ FrameResult VM__run_top_frame(VM* self) {
}
}
} else {
for(int i = 0; i < dict->length; i++) {
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
c11_sv name = py_name2sv(kv->key);
@ -1239,6 +1240,7 @@ FrameResult VM__run_top_frame(VM* self) {
}
frame = self->top_frame;
co_codes = frame->co->codes.data;
co_names = frame->co->names.data;
goto __ERROR;
}
}

View File

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

View File

@ -84,7 +84,8 @@ static bool disassemble(CodeObject* co) {
case OP_BEGIN_CLASS:
case OP_DELETE_GLOBAL:
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;
}
case OP_LOAD_FAST:

View File

@ -374,7 +374,7 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
}
if(ti->is_python) {
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];
if(kv->key == NULL) continue;
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);
buf->used_types[obj->type] = true;
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];
if(kv->key == NULL) continue;
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) {
PY_CHECK_ARGC(1);
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;
}

View File

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

View File

@ -225,6 +225,13 @@ char* py_formatexc() {
}
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__ctor(&buf);
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);
NameDict* dict = PyObject__dict(object->_obj);
py_newlist(py_retval());
for(int i = 0; i < dict->length; i++) {
py_Ref slot = py_list_emplace(py_retval());
py_Ref p = py_newtuple(slot, 2);
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
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[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) {
assert(self && self->is_ptr);
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];
if(kv->key == NULL) continue;
bool ok = f(kv->key, &kv->value, ctx);