mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
backup
This commit is contained in:
parent
c5a70ec4aa
commit
1bb104086b
@ -20,8 +20,8 @@
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K c11_sv
|
||||
#define V py_Name
|
||||
#define NAME c11_smallmap_v2n
|
||||
#define V int
|
||||
#define NAME c11_smallmap_v2d
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
|
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include "pocketpy/common/name.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/interpreter/heap.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
#include "pocketpy/interpreter/name.h"
|
||||
#include "pocketpy/interpreter/line_profiler.h"
|
||||
#include <time.h>
|
||||
|
||||
@ -49,6 +49,8 @@ typedef struct VM {
|
||||
py_TValue reg[8]; // users' registers
|
||||
void* ctx; // user-defined context
|
||||
|
||||
NameDict cached_names;
|
||||
|
||||
py_StackRef curr_class;
|
||||
py_StackRef curr_decl_based_function;
|
||||
TraceInfo trace_info;
|
||||
@ -56,7 +58,6 @@ typedef struct VM {
|
||||
LineProfiler line_profiler;
|
||||
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
|
||||
InternedNames names;
|
||||
FixedMemoryPool pool_frame;
|
||||
ManagedHeap heap;
|
||||
ValueStack stack; // put `stack` at the end for better cache locality
|
||||
|
@ -237,13 +237,13 @@ PK_API py_Name py_name(const char*);
|
||||
/// Convert a name to a null-terminated string.
|
||||
PK_API const char* py_name2str(py_Name);
|
||||
/// 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.
|
||||
PK_API py_Name py_namev(c11_sv);
|
||||
/// Convert a name to a `c11_sv`.
|
||||
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 *************/
|
||||
|
||||
|
@ -1,25 +1,96 @@
|
||||
#include "pocketpy/common/name.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include <stdatomic.h>
|
||||
|
||||
typedef struct InternedEntry InternedEntry;
|
||||
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 NameBucket NameBucket;
|
||||
|
||||
typedef struct {
|
||||
InternedEntry* table[1 << 16];
|
||||
typedef struct NameBucket {
|
||||
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;
|
||||
} InternedNames;
|
||||
} pk_string_table;
|
||||
|
||||
#define MAGIC_METHOD(x) py_Name x;
|
||||
#include "pocketpy/xmacros/magics.h"
|
||||
#undef MAGIC_METHOD
|
||||
|
||||
void pk_names_initialize() {
|
||||
|
||||
#define MAGIC_METHOD(x) x = py_name(#x);
|
||||
#include "pocketpy/xmacros/magics.h"
|
||||
#undef MAGIC_METHOD
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
@ -16,8 +16,8 @@
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K c11_sv
|
||||
#define V py_Name
|
||||
#define NAME c11_smallmap_v2n
|
||||
#define V int
|
||||
#define NAME c11_smallmap_v2d
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "pocketpy/compiler/compiler.h"
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/name.h"
|
||||
#include "pocketpy/compiler/lexer.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
@ -63,7 +64,7 @@ typedef struct Ctx {
|
||||
bool is_compiling_class;
|
||||
c11_vector /*T=Expr_p*/ s_expr;
|
||||
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;
|
||||
|
||||
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;
|
||||
c11_vector__ctor(&self->s_expr, sizeof(Expr*));
|
||||
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) {
|
||||
@ -1087,11 +1088,11 @@ static void Ctx__dtor(Ctx* self) {
|
||||
c11_vector__dtor(&self->s_expr);
|
||||
c11_smallmap_n2d__dtor(&self->global_names);
|
||||
// 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;
|
||||
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) {
|
||||
@ -1200,9 +1201,7 @@ static int Ctx__add_varname(Ctx* self, py_Name name) {
|
||||
return CodeObject__add_varname(self->co, name);
|
||||
}
|
||||
|
||||
static int Ctx__add_name(Ctx* self, py_Name name) {
|
||||
return CodeObject__add_name(self->co, name);
|
||||
}
|
||||
static int Ctx__add_name(Ctx* self, py_Name name) { return CodeObject__add_name(self->co, name); }
|
||||
|
||||
static int Ctx__add_const_string(Ctx* self, c11_sv key) {
|
||||
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;
|
||||
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) {
|
||||
return *val;
|
||||
} else {
|
||||
@ -1222,7 +1221,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
|
||||
char* new_buf = PK_MALLOC(key.size + 1);
|
||||
memcpy(new_buf, key.data, key.size);
|
||||
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},
|
||||
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 {
|
||||
NameExpr* e = NameExpr__new(prev()->line, decl_name, name_scope(self));
|
||||
vtemit_store((Expr*)e, ctx());
|
||||
@ -2404,7 +2403,7 @@ static Error* compile_class(Compiler* self, int decorators) {
|
||||
} else {
|
||||
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) {
|
||||
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());
|
||||
int index = Ctx__add_const_string(ctx(), type_hint);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -65,7 +65,6 @@ static void py_TypeInfo__ctor(py_TypeInfo* self,
|
||||
|
||||
void VM__ctor(VM* self) {
|
||||
self->top_frame = NULL;
|
||||
InternedNames__ctor(&self->names);
|
||||
|
||||
ModuleDict__ctor(&self->modules, "", *py_NIL());
|
||||
TypeList__ctor(&self->types);
|
||||
@ -97,6 +96,7 @@ void VM__ctor(VM* self) {
|
||||
|
||||
ManagedHeap__ctor(&self->heap);
|
||||
ValueStack__ctor(&self->stack);
|
||||
NameDict__ctor(&self->cached_names, PK_INST_ATTR_LOAD_FACTOR);
|
||||
|
||||
/* Init Builtin Types */
|
||||
// 0: unused
|
||||
@ -274,7 +274,7 @@ void VM__dtor(VM* self) {
|
||||
TypeList__dtor(&self->types);
|
||||
FixedMemoryPool__dtor(&self->pool_frame);
|
||||
ValueStack__dtor(&self->stack);
|
||||
InternedNames__dtor(&self->names);
|
||||
NameDict__dtor(&self->cached_names);
|
||||
}
|
||||
|
||||
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++) {
|
||||
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) {
|
||||
PyObject* obj = c11_vector__back(PyObject*, p_stack);
|
||||
@ -842,4 +835,16 @@ int py_replinput(char* buf, int max_size) {
|
||||
|
||||
buf[size] = '\0';
|
||||
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);
|
||||
}
|
@ -99,11 +99,31 @@ static bool disassemble(CodeObject* co) {
|
||||
pk_sprintf(&ss, " (%s)", decl->code.name->data);
|
||||
break;
|
||||
}
|
||||
case OP_BINARY_OP: {
|
||||
py_Name name = byte.arg & 0xFF;
|
||||
pk_sprintf(&ss, " (%s)", pk_op2str(name));
|
||||
break;
|
||||
}
|
||||
#define CASE_BINARY_OP(label, op, rop) \
|
||||
case label: { \
|
||||
pk_sprintf(&ss, " (%s)", pk_op2str(op)); \
|
||||
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);
|
||||
|
||||
|
@ -160,7 +160,7 @@ static void
|
||||
static bool _pk_compute_thread_flags[16];
|
||||
|
||||
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.",
|
||||
self->vm_index);
|
||||
}
|
||||
@ -187,7 +187,7 @@ static bool ComputeThread__new__(int argc, py_Ref argv) {
|
||||
c11_ComputeThread* self =
|
||||
py_newobject(py_retval(), py_totype(argv), 0, sizeof(c11_ComputeThread));
|
||||
self->vm_index = 0;
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
self->last_retval_data = NULL;
|
||||
self->last_retval_size = 0;
|
||||
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) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_ComputeThread* self = py_touserdata(argv);
|
||||
py_newbool(py_retval(), self->is_done);
|
||||
py_newbool(py_retval(), atomic_load(&self->is_done));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ComputeThread_wait_for_done(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_ComputeThread* self = py_touserdata(argv);
|
||||
while(!self->is_done)
|
||||
while(!atomic_load(&self->is_done)) {
|
||||
c11_thrd_yield();
|
||||
}
|
||||
py_newnone(py_retval());
|
||||
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) {
|
||||
PY_CHECK_ARGC(1);
|
||||
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) {
|
||||
py_newstr(py_retval(), self->last_error);
|
||||
} 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) {
|
||||
PY_CHECK_ARGC(1);
|
||||
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");
|
||||
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);
|
||||
self->last_retval_data = c11_memdup(retval_data, retval_size);
|
||||
self->last_retval_size = retval_size;
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return (c11_thrd_retval_t)0;
|
||||
|
||||
__ERROR:
|
||||
self->last_error = py_formatexc();
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
py_clearexc(p0);
|
||||
py_newnone(py_retval());
|
||||
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);
|
||||
self->last_retval_data = c11_memdup(retval_data, retval_size);
|
||||
self->last_retval_size = retval_size;
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return (c11_thrd_retval_t)0;
|
||||
|
||||
__ERROR:
|
||||
self->last_error = py_formatexc();
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
py_clearexc(p0);
|
||||
return (c11_thrd_retval_t)0;
|
||||
}
|
||||
@ -309,7 +310,7 @@ __ERROR:
|
||||
static bool ComputeThread_submit_exec(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
if(!ok) {
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return OSError("thrd_create() failed");
|
||||
}
|
||||
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) {
|
||||
PY_CHECK_ARGC(2);
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
if(!ok) {
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return OSError("thrd_create() failed");
|
||||
}
|
||||
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) {
|
||||
PY_CHECK_ARGC(4);
|
||||
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(2, tp_tuple);
|
||||
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;
|
||||
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);
|
||||
if(!ok) {
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return OSError("thrd_create() failed");
|
||||
}
|
||||
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,
|
||||
const char* source,
|
||||
enum py_CompileMode mode) {
|
||||
if(!self->is_done) return OSError("thread is not done yet");
|
||||
self->is_done = false;
|
||||
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
|
||||
atomic_store(&self->is_done, false);
|
||||
char* err = NULL;
|
||||
int old_vm_index = py_currentvm();
|
||||
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);
|
||||
py_switchvm(old_vm_index);
|
||||
bool ok = py_pickle_loads(retval_data, retval_size);
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
return ok;
|
||||
|
||||
__ERROR:
|
||||
err = py_formatexc();
|
||||
py_clearexc(p0);
|
||||
py_switchvm(old_vm_index);
|
||||
self->is_done = true;
|
||||
atomic_store(&self->is_done, true);
|
||||
RuntimeError("c11_ComputeThread__exec_blocked() failed:\n%s", err);
|
||||
PK_FREE(err);
|
||||
return false;
|
||||
@ -454,7 +455,7 @@ static void pk_ComputeThread__register(py_Ref mod) {
|
||||
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);
|
||||
py_TValue tmp;
|
||||
py_newint(&tmp, val);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/common/name.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
_Thread_local VM* pk_current_vm;
|
||||
@ -18,6 +19,8 @@ void py_initialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
pk_names_initialize();
|
||||
|
||||
// check endianness
|
||||
int x = 1;
|
||||
bool is_little_endian = *(char*)&x == 1;
|
||||
@ -62,6 +65,8 @@ void py_finalize() {
|
||||
pk_current_vm = &pk_default_vm;
|
||||
VM__dtor(&pk_default_vm);
|
||||
pk_current_vm = NULL;
|
||||
|
||||
pk_names_finalize();
|
||||
}
|
||||
|
||||
void py_switchvm(int index) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user