frame.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. void ValueStack__ctor(ValueStack* self) {
  9. self->sp = self->begin;
  10. self->end = self->begin + PK_VM_STACK_SIZE;
  11. }
  12. void ValueStack__dtor(ValueStack* self) { self->sp = self->begin; }
  13. void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) {
  14. py_StackRef dict = py_pushtmp();
  15. py_newdict(dict);
  16. c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
  17. py_TValue* value = &locals[entry->value];
  18. if(!py_isnil(value)) {
  19. bool ok = py_dict_setitem(dict, py_name2ref(entry->key), value);
  20. assert(ok);
  21. (void)ok;
  22. }
  23. }
  24. py_assign(py_retval(), dict);
  25. py_pop();
  26. }
  27. NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
  28. NameDict* dict = NameDict__new();
  29. c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
  30. py_TValue value = locals[entry->value];
  31. if(!py_isnil(&value)) NameDict__set(dict, entry->key, value);
  32. }
  33. return dict;
  34. }
  35. UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
  36. UnwindTarget* self = PK_MALLOC(sizeof(UnwindTarget));
  37. self->next = next;
  38. self->iblock = iblock;
  39. self->offset = offset;
  40. return self;
  41. }
  42. void UnwindTarget__delete(UnwindTarget* self) { PK_FREE(self); }
  43. Frame* Frame__new(const CodeObject* co,
  44. py_StackRef p0,
  45. py_GlobalRef module,
  46. py_Ref globals,
  47. py_Ref locals,
  48. bool is_locals_special) {
  49. assert(module->type == tp_module);
  50. assert(globals->type == tp_module || globals->type == tp_dict);
  51. if(is_locals_special) {
  52. assert(locals->type == tp_nil || locals->type == tp_locals || locals->type == tp_dict);
  53. }
  54. Frame* self = FixedMemoryPool__alloc(&pk_current_vm->pool_frame);
  55. self->f_back = NULL;
  56. self->co = co;
  57. self->p0 = p0;
  58. self->module = module;
  59. self->globals = globals;
  60. self->locals = locals;
  61. self->is_locals_special = is_locals_special;
  62. self->ip = -1;
  63. self->uw_list = NULL;
  64. return self;
  65. }
  66. void Frame__delete(Frame* self) {
  67. while(self->uw_list) {
  68. UnwindTarget* p = self->uw_list;
  69. self->uw_list = p->next;
  70. UnwindTarget__delete(p);
  71. }
  72. FixedMemoryPool__dealloc(&pk_current_vm->pool_frame, self);
  73. }
  74. int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
  75. // try to find a parent try block
  76. int iblock = Frame__iblock(self);
  77. while(iblock >= 0) {
  78. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  79. if(block->type == CodeBlockType_TRY) break;
  80. iblock = block->parent;
  81. }
  82. if(iblock < 0) return -1;
  83. UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
  84. _s->sp = (self->p0 + uw->offset); // unwind the stack
  85. return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
  86. }
  87. UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock) {
  88. UnwindTarget* uw;
  89. for(uw = self->uw_list; uw; uw = uw->next) {
  90. if(uw->iblock == iblock) return uw;
  91. }
  92. return NULL;
  93. }
  94. void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
  95. int iblock = Frame__iblock(self);
  96. UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
  97. if(existing) {
  98. existing->offset = sp - self->p0;
  99. } else {
  100. UnwindTarget* prev = self->uw_list;
  101. self->uw_list = UnwindTarget__new(prev, iblock, sp - self->p0);
  102. }
  103. }
  104. void Frame__gc_mark(Frame* self) {
  105. pk__mark_value(self->globals);
  106. if(self->is_locals_special) pk__mark_value(self->locals);
  107. CodeObject__gc_mark(self->co);
  108. }
  109. int Frame__lineno(const Frame* self) {
  110. int ip = self->ip;
  111. return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
  112. }
  113. int Frame__iblock(const Frame* self) {
  114. int ip = self->ip;
  115. return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
  116. }
  117. int Frame__getglobal(Frame* self, py_Name name) {
  118. if(self->globals->type == tp_module) {
  119. py_ItemRef item = py_getdict(self->globals, name);
  120. if(item != NULL) {
  121. py_assign(py_retval(), item);
  122. return 1;
  123. }
  124. return 0;
  125. } else {
  126. return py_dict_getitem(self->globals, py_name2ref(name));
  127. }
  128. }
  129. bool Frame__setglobal(Frame* self, py_Name name, py_TValue* val) {
  130. if(self->globals->type == tp_module) {
  131. py_setdict(self->globals, name, val);
  132. return true;
  133. } else {
  134. return py_dict_setitem(self->globals, py_name2ref(name), val);
  135. }
  136. }
  137. int Frame__delglobal(Frame* self, py_Name name) {
  138. if(self->globals->type == tp_module) {
  139. bool found = py_deldict(self->globals, name);
  140. return found ? 1 : 0;
  141. } else {
  142. return py_dict_delitem(self->globals, py_name2ref(name));
  143. }
  144. }
  145. py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name) {
  146. assert(!self->is_locals_special);
  147. int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1);
  148. if(index == -1) return NULL;
  149. return &self->locals[index];
  150. }
  151. py_Ref Frame__getclosure(Frame* self, py_Name name) {
  152. if(self->is_locals_special) return NULL;
  153. assert(self->p0->type == tp_function);
  154. Function* ud = py_touserdata(self->p0);
  155. if(ud->closure == NULL) return NULL;
  156. return NameDict__try_get(ud->closure, name);
  157. }