This commit is contained in:
blueloveTH 2025-06-04 19:37:30 +08:00
parent c5a70ec4aa
commit 1bb104086b
12 changed files with 178 additions and 140 deletions

View File

@ -20,8 +20,8 @@
#define SMALLMAP_T__HEADER #define SMALLMAP_T__HEADER
#define K c11_sv #define K c11_sv
#define V py_Name #define V int
#define NAME c11_smallmap_v2n #define NAME c11_smallmap_v2d
#define less(a, b) (c11_sv__cmp((a), (b)) < 0) #define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0) #define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
#include "pocketpy/xmacros/smallmap.h" #include "pocketpy/xmacros/smallmap.h"

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/common/name.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/interpreter/heap.h" #include "pocketpy/interpreter/heap.h"
#include "pocketpy/interpreter/frame.h" #include "pocketpy/interpreter/frame.h"
#include "pocketpy/interpreter/typeinfo.h" #include "pocketpy/interpreter/typeinfo.h"
#include "pocketpy/interpreter/name.h"
#include "pocketpy/interpreter/line_profiler.h" #include "pocketpy/interpreter/line_profiler.h"
#include <time.h> #include <time.h>
@ -49,6 +49,8 @@ typedef struct VM {
py_TValue reg[8]; // users' registers py_TValue reg[8]; // users' registers
void* ctx; // user-defined context void* ctx; // user-defined context
NameDict cached_names;
py_StackRef curr_class; py_StackRef curr_class;
py_StackRef curr_decl_based_function; py_StackRef curr_decl_based_function;
TraceInfo trace_info; TraceInfo trace_info;
@ -56,7 +58,6 @@ typedef struct VM {
LineProfiler line_profiler; LineProfiler line_profiler;
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES]; py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
InternedNames names;
FixedMemoryPool pool_frame; FixedMemoryPool pool_frame;
ManagedHeap heap; ManagedHeap heap;
ValueStack stack; // put `stack` at the end for better cache locality ValueStack stack; // put `stack` at the end for better cache locality

View File

@ -237,13 +237,13 @@ PK_API py_Name py_name(const char*);
/// Convert a name to a null-terminated string. /// Convert a name to a null-terminated string.
PK_API const char* py_name2str(py_Name); PK_API const char* py_name2str(py_Name);
/// Convert a name to a python `str` object with cache. /// Convert a name to a python `str` object with cache.
PK_API py_GlobalRef py_name2ref(py_Name); PK_API py_ItemRef py_name2ref(py_Name);
/// Convert a `c11_sv` to a name. /// Convert a `c11_sv` to a name.
PK_API py_Name py_namev(c11_sv); PK_API py_Name py_namev(c11_sv);
/// Convert a name to a `c11_sv`. /// Convert a name to a `c11_sv`.
PK_API c11_sv py_name2sv(py_Name); PK_API c11_sv py_name2sv(py_Name);
/// Check if the name matches the two underscores pattern. e.g. `__init__`, `__str__`, etc.
PK_API bool py_ismagicname(py_Name); #define py_ismagicname(name) (true)
/************* Meta Operations *************/ /************* Meta Operations *************/

View File

@ -1,25 +1,96 @@
#include "pocketpy/common/name.h" #include "pocketpy/common/name.h"
#include "pocketpy/common/str.h"
#include "pocketpy/pocketpy.h"
#include <stdatomic.h> #include <stdatomic.h>
typedef struct InternedEntry InternedEntry; typedef struct NameBucket NameBucket;
typedef struct InternedEntry{
InternedEntry* prev;
InternedEntry* next;
py_i64 hash;
int size; // size of the data excluding the null-terminator
char data[]; // null-terminated data
} InternedEntry;
typedef struct { typedef struct NameBucket {
InternedEntry* table[1 << 16]; NameBucket* next;
uint64_t hash;
int size; // size of the data excluding the null-terminator
char data[]; // null-terminated data
} NameBucket;
static struct {
NameBucket* table[0x10000];
atomic_bool lock; atomic_bool lock;
} InternedNames; } pk_string_table;
#define MAGIC_METHOD(x) py_Name x;
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
void pk_names_initialize() { void pk_names_initialize() {
#define MAGIC_METHOD(x) x = py_name(#x);
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
} }
void pk_names_finalize() { void pk_names_finalize() {
for(int i = 0; i < 0x10000; i++) {
NameBucket* p = pk_string_table.table[i];
while(p) {
NameBucket* next = p->next;
PK_FREE(p);
p = next;
}
pk_string_table.table[i] = NULL;
}
}
py_Name py_namev(c11_sv name) {
while(atomic_exchange(&pk_string_table.lock, true)) {
// 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];
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;
}
}
if(found) {
atomic_store(&pk_string_table.lock, false);
return (py_Name)p;
}
// generate new index
NameBucket* entry = PK_MALLOC(sizeof(NameBucket) + name.size + 1);
entry->next = NULL;
entry->hash = hash;
entry->size = name.size;
memcpy(entry->data, name.data, name.size);
entry->data[name.size] = '\0';
if(p == NULL) {
pk_string_table.table[index] = entry;
} else {
assert(p->next == NULL);
p->next = entry;
}
atomic_store(&pk_string_table.lock, false);
return (py_Name)entry;
}
c11_sv py_name2sv(py_Name index) {
NameBucket* p = (NameBucket*)index;
return (c11_sv){p->data, p->size};
}
py_Name py_name(const char* name) {
c11_sv sv;
sv.data = name;
sv.size = strlen(name);
return py_namev(sv);
}
const char* py_name2str(py_Name index) {
NameBucket* p = (NameBucket*)index;
return p->data;
} }

View File

@ -16,8 +16,8 @@
#define SMALLMAP_T__SOURCE #define SMALLMAP_T__SOURCE
#define K c11_sv #define K c11_sv
#define V py_Name #define V int
#define NAME c11_smallmap_v2n #define NAME c11_smallmap_v2d
#define less(a, b) (c11_sv__cmp((a), (b)) < 0) #define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0) #define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
#include "pocketpy/xmacros/smallmap.h" #include "pocketpy/xmacros/smallmap.h"

View File

@ -1,5 +1,6 @@
#include "pocketpy/compiler/compiler.h" #include "pocketpy/compiler/compiler.h"
#include "pocketpy/common/vector.h" #include "pocketpy/common/vector.h"
#include "pocketpy/common/name.h"
#include "pocketpy/compiler/lexer.h" #include "pocketpy/compiler/lexer.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
@ -63,7 +64,7 @@ typedef struct Ctx {
bool is_compiling_class; bool is_compiling_class;
c11_vector /*T=Expr_p*/ s_expr; c11_vector /*T=Expr_p*/ s_expr;
c11_smallmap_n2d global_names; c11_smallmap_n2d global_names;
c11_smallmap_v2n co_consts_string_dedup_map; // this stores 0-based index instead of pointer c11_smallmap_v2d co_consts_string_dedup_map; // this stores 0-based index instead of pointer
} Ctx; } Ctx;
typedef struct Expr Expr; typedef struct Expr Expr;
@ -1076,7 +1077,7 @@ static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) {
self->is_compiling_class = false; self->is_compiling_class = false;
c11_vector__ctor(&self->s_expr, sizeof(Expr*)); c11_vector__ctor(&self->s_expr, sizeof(Expr*));
c11_smallmap_n2d__ctor(&self->global_names); c11_smallmap_n2d__ctor(&self->global_names);
c11_smallmap_v2n__ctor(&self->co_consts_string_dedup_map); c11_smallmap_v2d__ctor(&self->co_consts_string_dedup_map);
} }
static void Ctx__dtor(Ctx* self) { static void Ctx__dtor(Ctx* self) {
@ -1087,11 +1088,11 @@ static void Ctx__dtor(Ctx* self) {
c11_vector__dtor(&self->s_expr); c11_vector__dtor(&self->s_expr);
c11_smallmap_n2d__dtor(&self->global_names); c11_smallmap_n2d__dtor(&self->global_names);
// free the dedup map // free the dedup map
c11__foreach(c11_smallmap_v2n_KV, &self->co_consts_string_dedup_map, p_kv) { c11__foreach(c11_smallmap_v2d_KV, &self->co_consts_string_dedup_map, p_kv) {
const char* p = p_kv->key.data; const char* p = p_kv->key.data;
PK_FREE((void*)p); PK_FREE((void*)p);
} }
c11_smallmap_v2n__dtor(&self->co_consts_string_dedup_map); c11_smallmap_v2d__dtor(&self->co_consts_string_dedup_map);
} }
static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break) { static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break) {
@ -1200,9 +1201,7 @@ static int Ctx__add_varname(Ctx* self, py_Name name) {
return CodeObject__add_varname(self->co, name); return CodeObject__add_varname(self->co, name);
} }
static int Ctx__add_name(Ctx* self, py_Name name) { static int Ctx__add_name(Ctx* self, py_Name name) { return CodeObject__add_name(self->co, name); }
return CodeObject__add_name(self->co, name);
}
static int Ctx__add_const_string(Ctx* self, c11_sv key) { static int Ctx__add_const_string(Ctx* self, c11_sv key) {
if(key.size > 100) { if(key.size > 100) {
@ -1211,7 +1210,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
int index = self->co->consts.length - 1; int index = self->co->consts.length - 1;
return index; return index;
} }
uintptr_t* val = c11_smallmap_v2n__try_get(&self->co_consts_string_dedup_map, key); int* val = c11_smallmap_v2d__try_get(&self->co_consts_string_dedup_map, key);
if(val) { if(val) {
return *val; return *val;
} else { } else {
@ -1222,7 +1221,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
char* new_buf = PK_MALLOC(key.size + 1); char* new_buf = PK_MALLOC(key.size + 1);
memcpy(new_buf, key.data, key.size); memcpy(new_buf, key.data, key.size);
new_buf[key.size] = 0; new_buf[key.size] = 0;
c11_smallmap_v2n__set(&self->co_consts_string_dedup_map, c11_smallmap_v2d__set(&self->co_consts_string_dedup_map,
(c11_sv){new_buf, key.size}, (c11_sv){new_buf, key.size},
index); index);
return index; return index;
@ -2376,7 +2375,7 @@ static Error* compile_function(Compiler* self, int decorators) {
} }
} }
Ctx__emit_(ctx(), OP_STORE_CLASS_ATTR, decl_name, prev()->line); Ctx__emit_(ctx(), OP_STORE_CLASS_ATTR, Ctx__add_name(ctx(), decl_name), prev()->line);
} else { } else {
NameExpr* e = NameExpr__new(prev()->line, decl_name, name_scope(self)); NameExpr* e = NameExpr__new(prev()->line, decl_name, name_scope(self));
vtemit_store((Expr*)e, ctx()); vtemit_store((Expr*)e, ctx());
@ -2404,7 +2403,7 @@ static Error* compile_class(Compiler* self, int decorators) {
} else { } else {
Ctx__s_emit_top(ctx()); // [] Ctx__s_emit_top(ctx()); // []
} }
Ctx__emit_(ctx(), OP_BEGIN_CLASS, name, BC_KEEPLINE); Ctx__emit_(ctx(), OP_BEGIN_CLASS, Ctx__add_name(ctx(), name), BC_KEEPLINE);
c11__foreach(Ctx, &self->contexts, it) { c11__foreach(Ctx, &self->contexts, it) {
if(it->is_compiling_class) return SyntaxError(self, "nested class is not allowed"); if(it->is_compiling_class) return SyntaxError(self, "nested class is not allowed");
@ -2788,7 +2787,10 @@ static Error* compile_stmt(Compiler* self) {
NameExpr* ne = (NameExpr*)Ctx__s_top(ctx()); NameExpr* ne = (NameExpr*)Ctx__s_top(ctx());
int index = Ctx__add_const_string(ctx(), type_hint); int index = Ctx__add_const_string(ctx(), type_hint);
Ctx__emit_(ctx(), OP_LOAD_CONST, index, BC_KEEPLINE); Ctx__emit_(ctx(), OP_LOAD_CONST, index, BC_KEEPLINE);
Ctx__emit_(ctx(), OP_ADD_CLASS_ANNOTATION, Ctx__add_name(ctx(), ne->name), BC_KEEPLINE); Ctx__emit_(ctx(),
OP_ADD_CLASS_ANNOTATION,
Ctx__add_name(ctx(), ne->name),
BC_KEEPLINE);
} }
} }
} }

View File

@ -1,67 +0,0 @@
#include "pocketpy/interpreter/name.h"
#include "pocketpy/interpreter/vm.h"
#define MAGIC_METHOD(x) py_Name x;
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
void InternedNames__ctor(InternedNames* self) {
c11_smallmap_v2n__ctor(&self->interned);
// initialize all magic names
#define MAGIC_METHOD(x) x = py_name(#x);
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
}
void InternedNames__dtor(InternedNames* self) {
for(int i = 0; i < self->interned.length; i++) {
c11_smallmap_v2n_KV* kv = c11__at(c11_smallmap_v2n_KV, &self->interned, i);
PK_FREE((void*)kv->value);
}
c11_smallmap_v2n__dtor(&self->interned);
}
py_Name py_name(const char* name) {
c11_sv sv;
sv.data = name;
sv.size = strlen(name);
return py_namev(sv);
}
py_Name py_namev(c11_sv name) {
InternedNames* self = &pk_current_vm->names;
py_Name index = c11_smallmap_v2n__get(&self->interned, name, 0);
if(index != 0) return index;
// generate new index
InternedEntry* p = PK_MALLOC(sizeof(InternedEntry) + name.size + 1);
p->size = name.size;
memcpy(p->data, name.data, name.size);
p->data[name.size] = '\0';
memset(&p->obj, 0, sizeof(py_TValue));
index = (py_Name)p;
// save to _interned
c11_smallmap_v2n__set(&self->interned, (c11_sv){p->data, name.size}, index);
return index;
}
const char* py_name2str(py_Name index) {
InternedEntry* p = (InternedEntry*)index;
return p->data;
}
c11_sv py_name2sv(py_Name index) {
InternedEntry* p = (InternedEntry*)index;
return (c11_sv){p->data, p->size};
}
py_GlobalRef py_name2ref(py_Name index) {
InternedEntry* p = (InternedEntry*)index;
if(p->obj.type == tp_nil) {
c11_sv sv;
sv.data = p->data;
sv.size = p->size;
py_newstrv(&p->obj, sv);
}
return &p->obj;
}

View File

@ -65,7 +65,6 @@ static void py_TypeInfo__ctor(py_TypeInfo* self,
void VM__ctor(VM* self) { void VM__ctor(VM* self) {
self->top_frame = NULL; self->top_frame = NULL;
InternedNames__ctor(&self->names);
ModuleDict__ctor(&self->modules, "", *py_NIL()); ModuleDict__ctor(&self->modules, "", *py_NIL());
TypeList__ctor(&self->types); TypeList__ctor(&self->types);
@ -97,6 +96,7 @@ void VM__ctor(VM* self) {
ManagedHeap__ctor(&self->heap); ManagedHeap__ctor(&self->heap);
ValueStack__ctor(&self->stack); ValueStack__ctor(&self->stack);
NameDict__ctor(&self->cached_names, PK_INST_ATTR_LOAD_FACTOR);
/* Init Builtin Types */ /* Init Builtin Types */
// 0: unused // 0: unused
@ -274,7 +274,7 @@ void VM__dtor(VM* self) {
TypeList__dtor(&self->types); TypeList__dtor(&self->types);
FixedMemoryPool__dtor(&self->pool_frame); FixedMemoryPool__dtor(&self->pool_frame);
ValueStack__dtor(&self->stack); ValueStack__dtor(&self->stack);
InternedNames__dtor(&self->names); NameDict__dtor(&self->cached_names);
} }
void VM__push_frame(VM* self, py_Frame* frame) { void VM__push_frame(VM* self, py_Frame* frame) {
@ -666,13 +666,6 @@ void ManagedHeap__mark(ManagedHeap* self) {
for(int i = 0; i < c11__count_array(vm->reg); i++) { for(int i = 0; i < c11__count_array(vm->reg); i++) {
pk__mark_value(&vm->reg[i]); pk__mark_value(&vm->reg[i]);
} }
// mark interned names
for(int i = 0; i < vm->names.interned.length; i++) {
c11_smallmap_v2n_KV* kv = c11__at(c11_smallmap_v2n_KV, &vm->names.interned, i);
InternedEntry* entry = (InternedEntry*)kv->value;
pk__mark_value(&entry->obj);
}
/*****************************/ /*****************************/
while(p_stack->length > 0) { while(p_stack->length > 0) {
PyObject* obj = c11_vector__back(PyObject*, p_stack); PyObject* obj = c11_vector__back(PyObject*, p_stack);
@ -842,4 +835,16 @@ int py_replinput(char* buf, int max_size) {
buf[size] = '\0'; buf[size] = '\0';
return size; return size;
}
py_Ref py_name2ref(py_Name name) {
assert(name != NULL);
NameDict* d = &pk_current_vm->cached_names;
py_Ref res = NameDict__try_get(d, name);
if(res != NULL) return res;
// not found, create a new one
py_TValue tmp;
py_newstrv(&tmp, py_name2sv(name));
NameDict__set(d, name, &tmp);
return NameDict__try_get(d, name);
} }

View File

@ -99,11 +99,31 @@ static bool disassemble(CodeObject* co) {
pk_sprintf(&ss, " (%s)", decl->code.name->data); pk_sprintf(&ss, " (%s)", decl->code.name->data);
break; break;
} }
case OP_BINARY_OP: { #define CASE_BINARY_OP(label, op, rop) \
py_Name name = byte.arg & 0xFF; case label: { \
pk_sprintf(&ss, " (%s)", pk_op2str(name)); pk_sprintf(&ss, " (%s)", pk_op2str(op)); \
break; break; \
} }
CASE_BINARY_OP(OP_BINARY_ADD, __add__, __radd__)
CASE_BINARY_OP(OP_BINARY_SUB, __sub__, __rsub__)
CASE_BINARY_OP(OP_BINARY_MUL, __mul__, __rmul__)
CASE_BINARY_OP(OP_BINARY_TRUEDIV, __truediv__, __rtruediv__)
CASE_BINARY_OP(OP_BINARY_FLOORDIV, __floordiv__, __rfloordiv__)
CASE_BINARY_OP(OP_BINARY_MOD, __mod__, __rmod__)
CASE_BINARY_OP(OP_BINARY_POW, __pow__, __rpow__)
CASE_BINARY_OP(OP_BINARY_LSHIFT, __lshift__, 0)
CASE_BINARY_OP(OP_BINARY_RSHIFT, __rshift__, 0)
CASE_BINARY_OP(OP_BINARY_AND, __and__, 0)
CASE_BINARY_OP(OP_BINARY_OR, __or__, 0)
CASE_BINARY_OP(OP_BINARY_XOR, __xor__, 0)
CASE_BINARY_OP(OP_BINARY_MATMUL, __matmul__, 0)
CASE_BINARY_OP(OP_COMPARE_LT, __lt__, __gt__)
CASE_BINARY_OP(OP_COMPARE_LE, __le__, __ge__)
CASE_BINARY_OP(OP_COMPARE_EQ, __eq__, __eq__)
CASE_BINARY_OP(OP_COMPARE_NE, __ne__, __ne__)
CASE_BINARY_OP(OP_COMPARE_GT, __gt__, __lt__)
CASE_BINARY_OP(OP_COMPARE_GE, __ge__, __le__)
#undef CASE_BINARY_OP
} }
} while(0); } while(0);

View File

@ -160,7 +160,7 @@ static void
static bool _pk_compute_thread_flags[16]; static bool _pk_compute_thread_flags[16];
static void c11_ComputeThread__dtor(c11_ComputeThread* self) { static void c11_ComputeThread__dtor(c11_ComputeThread* self) {
if(!self->is_done) { if(!atomic_load(&self->is_done)) {
c11__abort("ComputeThread(%d) is not done yet!! But the object was deleted.", c11__abort("ComputeThread(%d) is not done yet!! But the object was deleted.",
self->vm_index); self->vm_index);
} }
@ -187,7 +187,7 @@ static bool ComputeThread__new__(int argc, py_Ref argv) {
c11_ComputeThread* self = c11_ComputeThread* self =
py_newobject(py_retval(), py_totype(argv), 0, sizeof(c11_ComputeThread)); py_newobject(py_retval(), py_totype(argv), 0, sizeof(c11_ComputeThread));
self->vm_index = 0; self->vm_index = 0;
self->is_done = true; atomic_store(&self->is_done, true);
self->last_retval_data = NULL; self->last_retval_data = NULL;
self->last_retval_size = 0; self->last_retval_size = 0;
self->last_error = NULL; self->last_error = NULL;
@ -217,15 +217,16 @@ 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(), self->is_done); py_newbool(py_retval(), atomic_load(&self->is_done));
return true; return true;
} }
static bool ComputeThread_wait_for_done(int argc, py_Ref argv) { static bool ComputeThread_wait_for_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);
while(!self->is_done) while(!atomic_load(&self->is_done)) {
c11_thrd_yield(); c11_thrd_yield();
}
py_newnone(py_retval()); py_newnone(py_retval());
return true; return true;
} }
@ -233,7 +234,7 @@ static bool ComputeThread_wait_for_done(int argc, py_Ref argv) {
static bool ComputeThread_last_error(int argc, py_Ref argv) { static bool ComputeThread_last_error(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);
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
if(self->last_error) { if(self->last_error) {
py_newstr(py_retval(), self->last_error); py_newstr(py_retval(), self->last_error);
} else { } else {
@ -245,7 +246,7 @@ static bool ComputeThread_last_error(int argc, py_Ref argv) {
static bool ComputeThread_last_retval(int argc, py_Ref argv) { static bool ComputeThread_last_retval(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);
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
if(self->last_retval_data == NULL) return ValueError("no retval available"); if(self->last_retval_data == NULL) return ValueError("no retval available");
return py_pickle_loads(self->last_retval_data, self->last_retval_size); return py_pickle_loads(self->last_retval_data, self->last_retval_size);
} }
@ -273,12 +274,12 @@ static c11_thrd_retval_t ComputeThreadJob_call(void* arg) {
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size); unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
self->last_retval_data = c11_memdup(retval_data, retval_size); self->last_retval_data = c11_memdup(retval_data, retval_size);
self->last_retval_size = retval_size; self->last_retval_size = retval_size;
self->is_done = true; atomic_store(&self->is_done, true);
return (c11_thrd_retval_t)0; return (c11_thrd_retval_t)0;
__ERROR: __ERROR:
self->last_error = py_formatexc(); self->last_error = py_formatexc();
self->is_done = true; atomic_store(&self->is_done, true);
py_clearexc(p0); py_clearexc(p0);
py_newnone(py_retval()); py_newnone(py_retval());
return (c11_thrd_retval_t)0; return (c11_thrd_retval_t)0;
@ -296,12 +297,12 @@ static c11_thrd_retval_t ComputeThreadJob_exec(void* arg) {
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size); unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
self->last_retval_data = c11_memdup(retval_data, retval_size); self->last_retval_data = c11_memdup(retval_data, retval_size);
self->last_retval_size = retval_size; self->last_retval_size = retval_size;
self->is_done = true; atomic_store(&self->is_done, true);
return (c11_thrd_retval_t)0; return (c11_thrd_retval_t)0;
__ERROR: __ERROR:
self->last_error = py_formatexc(); self->last_error = py_formatexc();
self->is_done = true; atomic_store(&self->is_done, true);
py_clearexc(p0); py_clearexc(p0);
return (c11_thrd_retval_t)0; return (c11_thrd_retval_t)0;
} }
@ -309,7 +310,7 @@ __ERROR:
static bool ComputeThread_submit_exec(int argc, py_Ref argv) { static bool ComputeThread_submit_exec(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0)); c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1)); const char* source = py_tostr(py_arg(1));
/**************************/ /**************************/
@ -319,10 +320,10 @@ static bool ComputeThread_submit_exec(int argc, py_Ref argv) {
job->mode = EXEC_MODE; job->mode = EXEC_MODE;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor); c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor);
/**************************/ /**************************/
self->is_done = false; atomic_store(&self->is_done, false);
bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_exec, job); bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_exec, job);
if(!ok) { if(!ok) {
self->is_done = true; atomic_store(&self->is_done, true);
return OSError("thrd_create() failed"); return OSError("thrd_create() failed");
} }
py_newnone(py_retval()); py_newnone(py_retval());
@ -332,7 +333,7 @@ static bool ComputeThread_submit_exec(int argc, py_Ref argv) {
static bool ComputeThread_submit_eval(int argc, py_Ref argv) { static bool ComputeThread_submit_eval(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0)); c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1)); const char* source = py_tostr(py_arg(1));
/**************************/ /**************************/
@ -342,10 +343,10 @@ static bool ComputeThread_submit_eval(int argc, py_Ref argv) {
job->mode = EVAL_MODE; job->mode = EVAL_MODE;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor); c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor);
/**************************/ /**************************/
self->is_done = false; atomic_store(&self->is_done, false);
bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_exec, job); bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_exec, job);
if(!ok) { if(!ok) {
self->is_done = true; atomic_store(&self->is_done, true);
return OSError("thrd_create() failed"); return OSError("thrd_create() failed");
} }
py_newnone(py_retval()); py_newnone(py_retval());
@ -355,7 +356,7 @@ static bool ComputeThread_submit_eval(int argc, py_Ref argv) {
static bool ComputeThread_submit_call(int argc, py_Ref argv) { static bool ComputeThread_submit_call(int argc, py_Ref argv) {
PY_CHECK_ARGC(4); PY_CHECK_ARGC(4);
c11_ComputeThread* self = py_touserdata(py_arg(0)); c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_tuple); PY_CHECK_ARG_TYPE(2, tp_tuple);
PY_CHECK_ARG_TYPE(3, tp_dict); PY_CHECK_ARG_TYPE(3, tp_dict);
@ -379,10 +380,10 @@ static bool ComputeThread_submit_call(int argc, py_Ref argv) {
job->kwargs_size = kwargs_size; job->kwargs_size = kwargs_size;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobCall__dtor); c11_ComputeThread__reset_job(self, job, ComputeThreadJobCall__dtor);
/**************************/ /**************************/
self->is_done = false; atomic_store(&self->is_done, false);
bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_call, job); bool ok = c11_thrd_create(&self->thread, ComputeThreadJob_call, job);
if(!ok) { if(!ok) {
self->is_done = true; atomic_store(&self->is_done, true);
return OSError("thrd_create() failed"); return OSError("thrd_create() failed");
} }
py_newnone(py_retval()); py_newnone(py_retval());
@ -392,8 +393,8 @@ static bool ComputeThread_submit_call(int argc, py_Ref argv) {
static bool c11_ComputeThread__exec_blocked(c11_ComputeThread* self, static bool c11_ComputeThread__exec_blocked(c11_ComputeThread* self,
const char* source, const char* source,
enum py_CompileMode mode) { enum py_CompileMode mode) {
if(!self->is_done) return OSError("thread is not done yet"); if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
self->is_done = false; atomic_store(&self->is_done, false);
char* err = NULL; char* err = NULL;
int old_vm_index = py_currentvm(); int old_vm_index = py_currentvm();
py_switchvm(self->vm_index); py_switchvm(self->vm_index);
@ -405,14 +406,14 @@ static bool c11_ComputeThread__exec_blocked(c11_ComputeThread* self,
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size); unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
py_switchvm(old_vm_index); py_switchvm(old_vm_index);
bool ok = py_pickle_loads(retval_data, retval_size); bool ok = py_pickle_loads(retval_data, retval_size);
self->is_done = true; atomic_store(&self->is_done, true);
return ok; return ok;
__ERROR: __ERROR:
err = py_formatexc(); err = py_formatexc();
py_clearexc(p0); py_clearexc(p0);
py_switchvm(old_vm_index); py_switchvm(old_vm_index);
self->is_done = true; atomic_store(&self->is_done, true);
RuntimeError("c11_ComputeThread__exec_blocked() failed:\n%s", err); RuntimeError("c11_ComputeThread__exec_blocked() failed:\n%s", err);
PK_FREE(err); PK_FREE(err);
return false; return false;
@ -454,7 +455,7 @@ static void pk_ComputeThread__register(py_Ref mod) {
py_bindmethod(type, "eval", ComputeThread_eval); py_bindmethod(type, "eval", ComputeThread_eval);
} }
static void pkpy_configmacros_add(py_Ref dict, const char* key, int val){ static void pkpy_configmacros_add(py_Ref dict, const char* key, int val) {
assert(dict->type == tp_dict); assert(dict->type == tp_dict);
py_TValue tmp; py_TValue tmp;
py_newint(&tmp, val); py_newint(&tmp, val);

View File

@ -3,6 +3,7 @@
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/common/name.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
_Thread_local VM* pk_current_vm; _Thread_local VM* pk_current_vm;
@ -18,6 +19,8 @@ void py_initialize() {
return; return;
} }
pk_names_initialize();
// check endianness // check endianness
int x = 1; int x = 1;
bool is_little_endian = *(char*)&x == 1; bool is_little_endian = *(char*)&x == 1;
@ -62,6 +65,8 @@ void py_finalize() {
pk_current_vm = &pk_default_vm; pk_current_vm = &pk_default_vm;
VM__dtor(&pk_default_vm); VM__dtor(&pk_default_vm);
pk_current_vm = NULL; pk_current_vm = NULL;
pk_names_finalize();
} }
void py_switchvm(int index) { void py_switchvm(int index) {