frame.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "pocketpy/interpreter/frame.h"
  2. #include "pocketpy/common/memorypool.h"
  3. #include "pocketpy/interpreter/vm.h"
  4. #include "pocketpy/objects/base.h"
  5. #include "pocketpy/objects/codeobject.h"
  6. #include "pocketpy/pocketpy.h"
  7. #include <stdbool.h>
  8. #include <assert.h>
  9. void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) {
  10. py_StackRef dict = py_pushtmp();
  11. py_newdict(dict);
  12. c11__foreach(c11_smallmap_n2d_KV, &co->varnames_inv, entry) {
  13. py_TValue* value = &locals[entry->value];
  14. if(!py_isnil(value)) {
  15. bool ok = py_dict_setitem(dict, py_name2ref(entry->key), value);
  16. assert(ok);
  17. (void)ok;
  18. }
  19. }
  20. py_assign(py_retval(), dict);
  21. py_pop();
  22. }
  23. NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
  24. NameDict* dict = NameDict__new(PK_INST_ATTR_LOAD_FACTOR);
  25. c11__foreach(c11_smallmap_n2d_KV, &co->varnames_inv, entry) {
  26. py_Ref val = &locals[entry->value];
  27. if(!py_isnil(val)) NameDict__set(dict, entry->key, val);
  28. }
  29. return dict;
  30. }
  31. UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
  32. UnwindTarget* self = PK_MALLOC(sizeof(UnwindTarget));
  33. self->next = next;
  34. self->iblock = iblock;
  35. self->offset = offset;
  36. return self;
  37. }
  38. void UnwindTarget__delete(UnwindTarget* self) { PK_FREE(self); }
  39. py_Frame* Frame__new(const CodeObject* co,
  40. py_StackRef p0,
  41. py_GlobalRef module,
  42. py_Ref globals,
  43. py_Ref locals,
  44. bool is_locals_special) {
  45. assert(module->type == tp_module);
  46. assert(globals->type == tp_module || globals->type == tp_dict);
  47. if(is_locals_special) {
  48. assert(locals->type == tp_nil || locals->type == tp_locals || locals->type == tp_dict);
  49. }
  50. py_Frame* self = FixedMemoryPool__alloc(&pk_current_vm->pool_frame);
  51. self->f_back = NULL;
  52. self->co = co;
  53. self->p0 = p0;
  54. self->module = module;
  55. self->globals = globals;
  56. self->locals = locals;
  57. self->is_locals_special = is_locals_special;
  58. self->ip = -1;
  59. self->uw_list = NULL;
  60. return self;
  61. }
  62. void Frame__delete(py_Frame* self) {
  63. while(self->uw_list) {
  64. UnwindTarget* p = self->uw_list;
  65. self->uw_list = p->next;
  66. UnwindTarget__delete(p);
  67. }
  68. FixedMemoryPool__dealloc(&pk_current_vm->pool_frame, self);
  69. }
  70. int Frame__prepare_jump_exception_handler(py_Frame* self, ValueStack* _s) {
  71. // try to find a parent try block
  72. int iblock = Frame__iblock(self);
  73. while(iblock >= 0) {
  74. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  75. if(block->type == CodeBlockType_TRY) break;
  76. iblock = block->parent;
  77. }
  78. if(iblock < 0) return -1;
  79. UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
  80. _s->sp = (self->p0 + uw->offset); // unwind the stack
  81. return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
  82. }
  83. UnwindTarget* Frame__find_unwind_target(py_Frame* self, int iblock) {
  84. UnwindTarget* uw;
  85. for(uw = self->uw_list; uw; uw = uw->next) {
  86. if(uw->iblock == iblock) return uw;
  87. }
  88. return NULL;
  89. }
  90. void Frame__set_unwind_target(py_Frame* self, py_TValue* sp) {
  91. int iblock = Frame__iblock(self);
  92. assert(iblock >= 0);
  93. UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
  94. if(existing) {
  95. existing->offset = sp - self->p0;
  96. } else {
  97. UnwindTarget* prev = self->uw_list;
  98. self->uw_list = UnwindTarget__new(prev, iblock, sp - self->p0);
  99. }
  100. }
  101. void Frame__gc_mark(py_Frame* self, c11_vector* p_stack) {
  102. pk__mark_value(self->globals);
  103. if(self->is_locals_special) pk__mark_value(self->locals);
  104. CodeObject__gc_mark(self->co, p_stack);
  105. }
  106. int Frame__lineno(const py_Frame* self) {
  107. int ip = self->ip;
  108. if(ip >= 0) {
  109. BytecodeEx* ex = c11__at(BytecodeEx, &self->co->codes_ex, ip);
  110. return ex->lineno;
  111. }
  112. if(!self->is_locals_special) return self->co->start_line;
  113. return 0;
  114. }
  115. int Frame__iblock(const py_Frame* self) {
  116. int ip = self->ip;
  117. if(ip < 0) return -1;
  118. return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
  119. }
  120. int Frame__getglobal(py_Frame* self, py_Name name) {
  121. if(self->globals->type == tp_module) {
  122. py_ItemRef item = py_getdict(self->globals, name);
  123. if(item != NULL) {
  124. py_assign(py_retval(), item);
  125. return 1;
  126. }
  127. return 0;
  128. } else {
  129. return py_dict_getitem(self->globals, py_name2ref(name));
  130. }
  131. }
  132. bool Frame__setglobal(py_Frame* self, py_Name name, py_TValue* val) {
  133. if(self->globals->type == tp_module) {
  134. py_setdict(self->globals, name, val);
  135. return true;
  136. } else {
  137. return py_dict_setitem(self->globals, py_name2ref(name), val);
  138. }
  139. }
  140. int Frame__delglobal(py_Frame* self, py_Name name) {
  141. if(self->globals->type == tp_module) {
  142. bool found = py_deldict(self->globals, name);
  143. return found ? 1 : 0;
  144. } else {
  145. return py_dict_delitem(self->globals, py_name2ref(name));
  146. }
  147. }
  148. py_StackRef Frame__getlocal_noproxy(py_Frame* self, py_Name name) {
  149. assert(!self->is_locals_special);
  150. int index = c11_smallmap_n2d__get(&self->co->varnames_inv, name, -1);
  151. if(index == -1) return NULL;
  152. return &self->locals[index];
  153. }
  154. py_Ref Frame__getclosure(py_Frame* self, py_Name name) {
  155. if(self->is_locals_special) return NULL;
  156. assert(self->p0->type == tp_function);
  157. Function* ud = py_touserdata(self->p0);
  158. if(ud->closure == NULL) return NULL;
  159. return NameDict__try_get(ud->closure, name);
  160. }
  161. SourceLocation Frame__source_location(py_Frame* self) {
  162. SourceLocation loc;
  163. loc.lineno = Frame__lineno(self);
  164. loc.src = self->co->src;
  165. return loc;
  166. }
  167. const char* py_Frame_sourceloc(py_Frame* self, int* lineno) {
  168. SourceLocation loc = Frame__source_location(self);
  169. *lineno = loc.lineno;
  170. return loc.src->filename->data;
  171. }
  172. void py_Frame_newglobals(py_Frame* frame, py_OutRef out) {
  173. if(!frame) {
  174. pk_mappingproxy__namedict(out, pk_current_vm->main);
  175. return;
  176. }
  177. if(frame->globals->type == tp_module) {
  178. pk_mappingproxy__namedict(out, frame->globals);
  179. } else {
  180. *out = *frame->globals; // dict
  181. }
  182. }
  183. void py_Frame_newlocals(py_Frame* frame, py_OutRef out) {
  184. if(!frame) {
  185. py_newdict(out);
  186. return;
  187. }
  188. if(frame->is_locals_special) {
  189. switch(frame->locals->type) {
  190. case tp_locals: frame = frame->locals->_ptr; break;
  191. case tp_dict: *out = *frame->locals; return;
  192. case tp_nil: py_newdict(out); return;
  193. default: c11__unreachable();
  194. }
  195. }
  196. FastLocals__to_dict(frame->locals, frame->co);
  197. py_assign(out, py_retval());
  198. }
  199. py_StackRef py_Frame_function(py_Frame* self) {
  200. if(self->is_locals_special) return NULL;
  201. assert(self->p0->type == tp_function);
  202. return self->p0;
  203. }