This commit is contained in:
blueloveTH 2024-07-02 11:47:56 +08:00
parent a59a68b6f5
commit ab0f07bbd7
15 changed files with 118 additions and 89 deletions

View File

@ -22,6 +22,12 @@ typedef struct c11_string{
const char data[]; // flexible array member const char data[]; // flexible array member
} c11_string; } c11_string;
/* bytes */
typedef struct c11_bytes{
int size;
unsigned char data[]; // flexible array member
} c11_bytes;
int c11_sv__cmp(c11_sv self, c11_sv other); int c11_sv__cmp(c11_sv self, c11_sv other);
int c11_sv__cmp2(c11_sv self, const char* other, int size); int c11_sv__cmp2(c11_sv self, const char* other, int size);
int c11_sv__cmp3(c11_sv self, const char* other); int c11_sv__cmp3(c11_sv self, const char* other);

View File

@ -89,6 +89,8 @@ py_Type pk_VM__new_type(pk_VM* self,
bool subclass_enabled); bool subclass_enabled);
// type registration // type registration
py_Type pk_str__register();
py_Type pk_bytes__register();
py_Type pk_list__register(); py_Type pk_list__register();
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -7,40 +7,29 @@
extern "C" { extern "C" {
#endif #endif
typedef struct PyObject{ typedef struct PyObject {
py_Type type; // we have a duplicated type here for convenience py_Type type; // we have a duplicated type here for convenience
bool gc_is_large; bool gc_is_large;
bool gc_marked; bool gc_marked;
int slots; // number of slots in the object int slots; // number of slots in the object
char flex[];
} PyObject; } PyObject;
// slots >= 0, allocate N slots // slots >= 0, allocate N slots
// slots == -1, allocate a dict // slots == -1, allocate a dict
// | 8 bytes HEADER | <N slots> | <value> // | HEADER | <N slots> | <userdata>
// | 8 bytes HEADER | <dict> | <value> // | HEADER | <dict> | <userdata>
static_assert(sizeof(PyObject) <= 8, "!(sizeof(PyObject) <= 8)");
py_TValue* PyObject__slots(PyObject* self); py_TValue* PyObject__slots(PyObject* self);
pk_NameDict* PyObject__dict(PyObject* self); pk_NameDict* PyObject__dict(PyObject* self);
void* PyObject__value(PyObject* self); void* PyObject__userdata(PyObject* self);
#define PK_OBJ_HEADER_SIZE(slots) ((slots)>=0 ? 8+sizeof(py_TValue)*(slots) : 8+sizeof(pk_NameDict)) #define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(pk_NameDict))
PyObject* PyObject__new(py_Type type, int slots, int size); PyObject* PyObject__new(py_Type type, int slots, int size);
void PyObject__delete(PyObject* self); void PyObject__delete(PyObject* self);
PK_INLINE py_TValue PyVar__fromobj(PyObject* obj){
if(!obj) return PY_NULL;
py_TValue retval = {
.type = obj->type,
.is_ptr = true,
._obj = obj
};
return retval;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -55,7 +55,7 @@ void py_newbool(py_Ref, bool);
void py_newstr(py_Ref, const char*); void py_newstr(py_Ref, const char*);
void py_newstrn(py_Ref, const char*, int); void py_newstrn(py_Ref, const char*, int);
// void py_newfstr(py_Ref, const char*, ...); // void py_newfstr(py_Ref, const char*, ...);
void py_newbytes(py_Ref, const unsigned char*, int); unsigned char* py_newbytes(py_Ref, int);
void py_newnone(py_Ref); void py_newnone(py_Ref);
void py_newnotimplemented(py_Ref out); void py_newnotimplemented(py_Ref out);
void py_newellipsis(py_Ref out); void py_newellipsis(py_Ref out);
@ -104,7 +104,7 @@ bool py_tobool(const py_Ref);
py_Type py_totype(const py_Ref); py_Type py_totype(const py_Ref);
const char* py_tostr(const py_Ref); const char* py_tostr(const py_Ref);
const char* py_tostrn(const py_Ref, int* size); const char* py_tostrn(const py_Ref, int* size);
const unsigned char* py_tobytes(const py_Ref, int* size); unsigned char* py_tobytes(const py_Ref, int* size);
void* py_touserdata(const py_Ref); void* py_touserdata(const py_Ref);

View File

@ -8,6 +8,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
c11_string* c11_string__new(const char* data) { return c11_string__new2(data, strlen(data)); } c11_string* c11_string__new(const char* data) { return c11_string__new2(data, strlen(data)); }
c11_string* c11_string__new2(const char* data, int size) { c11_string* c11_string__new2(const char* data, int size) {

View File

@ -1354,7 +1354,7 @@ int Ctx__add_const_string(Ctx* self, c11_sv key) {
c11_vector__push(py_TValue, &self->co->consts, tmp); c11_vector__push(py_TValue, &self->co->consts, tmp);
int index = self->co->consts.count - 1; int index = self->co->consts.count - 1;
c11_smallmap_s2n__set(&self->co_consts_string_dedup_map, c11_smallmap_s2n__set(&self->co_consts_string_dedup_map,
c11_string__sv(PyObject__value(tmp._obj)), c11_string__sv(PyObject__userdata(tmp._obj)),
index); index);
return index; return index;
} }

View File

@ -426,9 +426,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
case OP_BUILD_BYTES: { case OP_BUILD_BYTES: {
int size; int size;
const char* data = py_tostrn(TOP(), &size); const char* data = py_tostrn(TOP(), &size);
unsigned char* p = (unsigned char*)malloc(size); unsigned char* p = py_newbytes(TOP(), size);
memcpy(p, data, size); memcpy(p, data, size);
py_newbytes(TOP(), p, size);
DISPATCH(); DISPATCH();
} }
case OP_BUILD_TUPLE: { case OP_BUILD_TUPLE: {

View File

@ -1,5 +1,6 @@
#include "pocketpy/interpreter/gc.h" #include "pocketpy/interpreter/gc.h"
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/objects/base.h"
void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){ void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){
c11_vector__ctor(&self->no_gc, sizeof(PyObject*)); c11_vector__ctor(&self->no_gc, sizeof(PyObject*));
@ -104,7 +105,8 @@ PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap *self, py_Type type, int slots, i
PyObject* PyObject__new(py_Type type, int slots, int size){ PyObject* PyObject__new(py_Type type, int slots, int size){
assert(slots >= 0 || slots == -1); assert(slots >= 0 || slots == -1);
PyObject* self; PyObject* self;
size += PK_OBJ_HEADER_SIZE(slots); // header + slots + udsize
size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + size;
if(size <= kPoolObjectBlockSize){ if(size <= kPoolObjectBlockSize){
self = PoolObject_alloc(); self = PoolObject_alloc();
self->gc_is_large = false; self->gc_is_large = false;

View File

@ -38,7 +38,11 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
// create type object with __dict__ // create type object with __dict__
pk_ManagedHeap* heap = &pk_current_vm->heap; pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type)); PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
self->self = PyVar__fromobj(typeobj); self->self = (py_TValue){
.type = typeobj->type,
.is_ptr = true,
._obj = typeobj,
};
self->module = module ? *module : PY_NULL; self->module = module ? *module : PY_NULL;
self->subclass_enabled = subclass_enabled; self->subclass_enabled = subclass_enabled;
@ -84,7 +88,7 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false)); validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false));
validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false)); validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false));
validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false)); validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
validate(tp_str, pk_VM__new_type(self, "str", tp_object, NULL, false)); validate(tp_str, pk_str__register());
validate(tp_list, pk_list__register()); validate(tp_list, pk_list__register());
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false));
@ -99,7 +103,7 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_super, pk_VM__new_type(self, "super", tp_object, NULL, false)); validate(tp_super, pk_VM__new_type(self, "super", tp_object, NULL, false));
validate(tp_exception, pk_VM__new_type(self, "Exception", tp_object, NULL, true)); validate(tp_exception, pk_VM__new_type(self, "Exception", tp_object, NULL, true));
validate(tp_bytes, pk_VM__new_type(self, "bytes", tp_object, NULL, false)); validate(tp_bytes, pk_bytes__register());
validate(tp_mappingproxy, pk_VM__new_type(self, "mappingproxy", tp_object, NULL, false)); validate(tp_mappingproxy, pk_VM__new_type(self, "mappingproxy", tp_object, NULL, false));
validate(tp_dict, pk_VM__new_type(self, "dict", tp_object, NULL, true)); validate(tp_dict, pk_VM__new_type(self, "dict", tp_object, NULL, true));
@ -191,7 +195,7 @@ py_Type pk_VM__new_type(pk_VM* self,
/****************************************/ /****************************************/
void PyObject__delete(PyObject* self) { void PyObject__delete(PyObject* self) {
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type); pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
if(ti->dtor) ti->dtor(PyObject__value(self)); if(ti->dtor) ti->dtor(PyObject__userdata(self));
if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self)); if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self));
if(self->gc_is_large) { if(self->gc_is_large) {
free(self); free(self);

View File

@ -2,16 +2,14 @@
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include <assert.h> #include <assert.h>
void* PyObject__value(PyObject* self){ void* PyObject__userdata(PyObject* self) { return self->flex + PK_OBJ_SLOTS_SIZE(self->slots); }
return (char*)self + PK_OBJ_HEADER_SIZE(self->slots);
}
pk_NameDict* PyObject__dict(PyObject* self){ pk_NameDict* PyObject__dict(PyObject* self) {
assert(self->slots == -1); assert(self->slots == -1);
return (pk_NameDict*)((char*)self + 8); return (pk_NameDict*)(self->flex);
} }
py_TValue* PyObject__slots(PyObject* self){ py_TValue* PyObject__slots(PyObject* self) {
assert(self->slots >= 0); assert(self->slots >= 0);
return (py_TValue*)((char*)self + 8); return (py_TValue*)(self->flex);
} }

View File

@ -1,3 +1,4 @@
#include "pocketpy/common/str.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
@ -33,29 +34,9 @@ py_Type py_totype(const py_Ref self) {
return *ud; return *ud;
} }
const char* py_tostr(const py_Ref self) {
assert(self->type == tp_str);
c11_string* ud = PyObject__value(self->_obj);
return ud->data;
}
const char* py_tostrn(const py_Ref self, int* size) {
assert(self->type == tp_str);
c11_string* ud = PyObject__value(self->_obj);
*size = ud->size;
return ud->data;
}
const unsigned char* py_tobytes(const py_Ref self, int* size) {
assert(self->type == tp_bytes);
int* ud = PyObject__value(self->_obj);
*size = *ud;
return (unsigned char*)(ud + 1);
}
void* py_touserdata(const py_Ref self) { void* py_touserdata(const py_Ref self) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
return PyObject__value(self->_obj); return PyObject__userdata(self->_obj);
} }
bool py_istype(const py_Ref self, py_Type type) { return self->type == type; } bool py_istype(const py_Ref self, py_Type type) { return self->type == type; }

View File

@ -4,19 +4,23 @@
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
py_Ref py_getmodule(const char *name){ py_Ref py_getmodule(const char* name) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
return pk_NameDict__try_get(&vm->modules, py_name(name)); return pk_NameDict__try_get(&vm->modules, py_name(name));
} }
py_Ref py_newmodule(const char *name, const char *package){ py_Ref py_newmodule(const char* name, const char* package) {
pk_ManagedHeap* heap = &pk_current_vm->heap; pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0); PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0);
py_Ref r0 = py_pushtmp(); py_Ref r0 = py_pushtmp();
py_Ref r1 = py_pushtmp(); py_Ref r1 = py_pushtmp();
*r0 = PyVar__fromobj(obj); *r0 = (py_TValue){
.type = obj->type,
.is_ptr = true,
._obj = obj,
};
py_newstr(r1, name); py_newstr(r1, name);
py_setdict(r0, __name__, r1); py_setdict(r0, __name__, r1);
@ -27,7 +31,7 @@ py_Ref py_newmodule(const char *name, const char *package){
py_setdict(r0, __package__, r1); py_setdict(r0, __package__, r1);
// convert to fullname // convert to fullname
if(package[0] != '\0'){ if(package[0] != '\0') {
// package.name // package.name
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "%s.%s", package, name); snprintf(buf, sizeof(buf), "%s.%s", package, name);

View File

@ -17,7 +17,7 @@ py_Type pk_list__register() {
void py_newlist(py_Ref out) { void py_newlist(py_Ref out) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List)); PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List));
List* userdata = PyObject__value(obj); List* userdata = PyObject__userdata(obj);
c11_vector__ctor(userdata, sizeof(py_TValue)); c11_vector__ctor(userdata, sizeof(py_TValue));
out->type = tp_list; out->type = tp_list;
out->is_ptr = true; out->is_ptr = true;

68
src/public/py_str.c Normal file
View File

@ -0,0 +1,68 @@
#include "pocketpy/common/str.h"
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
py_Type pk_str__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "str", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
return type;
}
py_Type pk_bytes__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "bytes", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
return type;
}
void py_newstr(py_Ref out, const char* data) {
return py_newstrn(out, data, strlen(data));
}
void py_newstrn(py_Ref out, const char* data, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
int total_size = sizeof(c11_string) + size + 1;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, total_size);
c11_string* ud = PyObject__userdata(obj);
c11_string__ctor2(ud, data, size);
out->type = tp_str;
out->is_ptr = true;
out->_obj = obj;
}
unsigned char* py_newbytes(py_Ref out, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
// 4 bytes size + data
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
c11_bytes* ud = PyObject__userdata(obj);
ud->size = size;
out->type = tp_bytes;
out->is_ptr = true;
out->_obj = obj;
return ud->data;
}
const char* py_tostr(const py_Ref self) {
assert(self->type == tp_str);
c11_string* ud = PyObject__userdata(self->_obj);
return ud->data;
}
const char* py_tostrn(const py_Ref self, int* size) {
assert(self->type == tp_str);
c11_string* ud = PyObject__userdata(self->_obj);
*size = ud->size;
return ud->data;
}
unsigned char* py_tobytes(const py_Ref self, int* size) {
assert(self->type == tp_bytes);
c11_bytes* ud = PyObject__userdata(self->_obj);
*size = ud->size;
return ud->data;
}

View File

@ -1,3 +1,5 @@
#include "pocketpy/common/str.h"
#include "pocketpy/common/vector.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
@ -37,35 +39,8 @@ void py_newellipsis(py_Ref out) {
out->is_ptr = false; out->is_ptr = false;
} }
void py_newnull(py_Ref out) { out->type = 0; } void py_newnull(py_Ref out) { out->type = 0; }
void py_newstr(py_Ref out, const char* data) {
return py_newstrn(out, data, strlen(data));
}
void py_newstrn(py_Ref out, const char* data, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
int total_size = sizeof(c11_string) + size + 1;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, total_size);
c11_string* ud = PyObject__value(obj);
c11_string__ctor2(ud, data, size);
out->type = tp_str;
out->is_ptr = true;
out->_obj = obj;
}
void py_newbytes(py_Ref out, const unsigned char* data, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
// 4 bytes size + data
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(int) + size);
int* psize = (int*)PyObject__value(obj);
*psize = size;
memcpy(psize + 1, data, size);
out->type = tp_bytes;
out->is_ptr = true;
out->_obj = obj;
}
void py_newfunction(py_Ref out, py_CFunction f, const char* sig) { void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL); py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL);