blueloveTH 1 год назад
Родитель
Сommit
ab0f07bbd7

+ 6 - 0
include/pocketpy/common/str.h

@@ -22,6 +22,12 @@ typedef struct c11_string{
     const char data[];      // flexible array member
 } 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__cmp2(c11_sv self, const char* other, int size);
 int c11_sv__cmp3(c11_sv self, const char* other);

+ 2 - 0
include/pocketpy/interpreter/vm.h

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

+ 8 - 19
include/pocketpy/objects/object.h

@@ -7,40 +7,29 @@
 extern "C" {
 #endif
 
-typedef struct PyObject{
-    py_Type type;          // we have a duplicated type here for convenience
+typedef struct PyObject {
+    py_Type type;  // we have a duplicated type here for convenience
     bool gc_is_large;
     bool gc_marked;
-    int slots;          // number of slots in the object
+    int slots;  // number of slots in the object
+    char flex[];
 } PyObject;
 
 // slots >= 0, allocate N slots
 // slots == -1, allocate a dict
 
-// | 8 bytes HEADER | <N slots> | <value>
-// | 8 bytes HEADER | <dict>    | <value>
-
-static_assert(sizeof(PyObject) <= 8, "!(sizeof(PyObject) <= 8)");
+// | HEADER | <N slots> | <userdata>
+// | HEADER | <dict>    | <userdata>
 
 py_TValue* PyObject__slots(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);
 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
 }
 #endif

+ 2 - 2
include/pocketpy/pocketpy.h

@@ -55,7 +55,7 @@ void py_newbool(py_Ref, bool);
 void py_newstr(py_Ref, const char*);
 void py_newstrn(py_Ref, const char*, int);
 // 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_newnotimplemented(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);
 const char* py_tostr(const py_Ref);
 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);
 

+ 1 - 0
src/common/str.c

@@ -8,6 +8,7 @@
 #include <ctype.h>
 #include <stdio.h>
 
+
 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) {

+ 1 - 1
src/compiler/compiler.c

@@ -1354,7 +1354,7 @@ int Ctx__add_const_string(Ctx* self, c11_sv key) {
         c11_vector__push(py_TValue, &self->co->consts, tmp);
         int index = self->co->consts.count - 1;
         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);
         return index;
     }

+ 1 - 2
src/interpreter/ceval.c

@@ -426,9 +426,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             case OP_BUILD_BYTES: {
                 int 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);
-                py_newbytes(TOP(), p, size);
                 DISPATCH();
             }
             case OP_BUILD_TUPLE: {

+ 3 - 1
src/interpreter/gc.c

@@ -1,5 +1,6 @@
 #include "pocketpy/interpreter/gc.h"
 #include "pocketpy/common/memorypool.h"
+#include "pocketpy/objects/base.h"
 
 void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){
     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){
     assert(slots >= 0 || slots == -1);
     PyObject* self;
-    size += PK_OBJ_HEADER_SIZE(slots);
+    // header + slots + udsize
+    size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + size;
     if(size <= kPoolObjectBlockSize){
         self = PoolObject_alloc();
         self->gc_is_large = false;

+ 8 - 4
src/interpreter/vm.c

@@ -38,7 +38,11 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
     // create type object with __dict__
     pk_ManagedHeap* heap = &pk_current_vm->heap;
     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->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_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_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_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_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_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) {
     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->gc_is_large) {
         free(self);

+ 5 - 7
src/objects/object.c

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

+ 2 - 21
src/public/cast.c

@@ -1,3 +1,4 @@
+#include "pocketpy/common/str.h"
 #include "pocketpy/pocketpy.h"
 
 #include "pocketpy/common/utils.h"
@@ -33,29 +34,9 @@ py_Type py_totype(const py_Ref self) {
     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) {
     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; }

+ 8 - 4
src/public/modules.c

@@ -4,19 +4,23 @@
 #include "pocketpy/objects/object.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;
     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;
     PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0);
 
     py_Ref r0 = 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_setdict(r0, __name__, r1);
@@ -27,7 +31,7 @@ py_Ref py_newmodule(const char *name, const char *package){
     py_setdict(r0, __package__, r1);
 
     // convert to fullname
-    if(package[0] != '\0'){
+    if(package[0] != '\0') {
         // package.name
         char buf[256];
         snprintf(buf, sizeof(buf), "%s.%s", package, name);

+ 1 - 1
src/public/py_list.c

@@ -17,7 +17,7 @@ py_Type pk_list__register() {
 void py_newlist(py_Ref out) {
     pk_VM* vm = pk_current_vm;
     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));
     out->type = tp_list;
     out->is_ptr = true;

+ 68 - 0
src/public/py_str.c

@@ -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;
+}
+

+ 2 - 27
src/public/values.c

@@ -1,3 +1,5 @@
+#include "pocketpy/common/str.h"
+#include "pocketpy/common/vector.h"
 #include "pocketpy/pocketpy.h"
 
 #include "pocketpy/common/utils.h"
@@ -37,35 +39,8 @@ void py_newellipsis(py_Ref out) {
     out->is_ptr = false;
 }
 
-
 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) {
     py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL);