frame.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "pocketpy/interpreter/frame.h"
  2. #include "pocketpy/interpreter/vm.h"
  3. #include "pocketpy/objects/base.h"
  4. #include "pocketpy/objects/codeobject.h"
  5. #include "pocketpy/pocketpy.h"
  6. #include <stdbool.h>
  7. void ValueStack__ctor(ValueStack* self) {
  8. self->sp = self->begin;
  9. self->end = self->begin + PK_VM_STACK_SIZE;
  10. }
  11. void ValueStack__clear(ValueStack* self) { self->sp = self->begin; }
  12. py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name) {
  13. int index = c11_smallmap_n2i__get(&co->varnames_inv, name, -1);
  14. if(index == -1) return NULL;
  15. return &locals[index];
  16. }
  17. NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
  18. NameDict* dict = NameDict__new();
  19. c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
  20. py_TValue value = locals[entry->value];
  21. if(!py_isnil(&value)) { NameDict__set(dict, entry->key, value); }
  22. }
  23. return dict;
  24. }
  25. UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
  26. UnwindTarget* self = malloc(sizeof(UnwindTarget));
  27. self->next = next;
  28. self->iblock = iblock;
  29. self->offset = offset;
  30. return self;
  31. }
  32. void UnwindTarget__delete(UnwindTarget* self) { free(self); }
  33. Frame* Frame__new(const CodeObject* co,
  34. py_GlobalRef module,
  35. py_StackRef p0,
  36. py_StackRef locals,
  37. bool has_function) {
  38. static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
  39. Frame* self = PoolFrame_alloc();
  40. self->f_back = NULL;
  41. self->ip = (Bytecode*)co->codes.data - 1;
  42. self->co = co;
  43. self->module = module;
  44. self->p0 = p0;
  45. self->locals = locals;
  46. self->has_function = has_function;
  47. self->is_dynamic = co->src->is_dynamic;
  48. self->uw_list = NULL;
  49. return self;
  50. }
  51. void Frame__delete(Frame* self) {
  52. while(self->uw_list) {
  53. UnwindTarget* p = self->uw_list;
  54. self->uw_list = p->next;
  55. UnwindTarget__delete(p);
  56. }
  57. PoolFrame_dealloc(self);
  58. }
  59. int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
  60. // try to find a parent try block
  61. int iblock = Frame__iblock(self);
  62. while(iblock >= 0) {
  63. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  64. if(block->type == CodeBlockType_TRY) break;
  65. iblock = block->parent;
  66. }
  67. if(iblock < 0) return -1;
  68. UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
  69. _s->sp = (self->locals + uw->offset); // unwind the stack
  70. return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
  71. }
  72. void Frame__prepare_jump_break(Frame* self, ValueStack* _s, int target) {
  73. int iblock = Frame__iblock(self);
  74. if(target >= self->co->codes.length) {
  75. while(iblock >= 0)
  76. iblock = Frame__exit_block(self, _s, iblock);
  77. } else {
  78. // BUG (solved)
  79. // for i in range(4):
  80. // _ = 0
  81. // # if there is no op here, the block check will fail
  82. // while i: --i
  83. int next_block = c11__at(BytecodeEx, &self->co->codes_ex, target)->iblock;
  84. while(iblock >= 0 && iblock != next_block)
  85. iblock = Frame__exit_block(self, _s, iblock);
  86. assert(iblock == next_block);
  87. }
  88. }
  89. int Frame__exit_block(Frame* self, ValueStack* _s, int iblock) {
  90. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  91. if(block->type == CodeBlockType_FOR_LOOP || block->type == CodeBlockType_WITH) {
  92. _s->sp--; // pop iterator or context variable
  93. } else if(block->type == CodeBlockType_EXCEPT || block->type == CodeBlockType_FINALLY) {
  94. py_clearexc(NULL);
  95. }
  96. return block->parent;
  97. }
  98. UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock) {
  99. UnwindTarget* uw;
  100. for(uw = self->uw_list; uw; uw = uw->next) {
  101. if(uw->iblock == iblock) return uw;
  102. }
  103. return NULL;
  104. }
  105. void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
  106. int iblock = Frame__iblock(self);
  107. UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
  108. if(existing) {
  109. existing->offset = sp - self->locals;
  110. } else {
  111. UnwindTarget* prev = self->uw_list;
  112. self->uw_list = UnwindTarget__new(prev, iblock, sp - self->locals);
  113. }
  114. }
  115. void Frame__gc_mark(Frame* self) {
  116. pk__mark_value(self->module);
  117. CodeObject__gc_mark(self->co);
  118. }
  119. py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
  120. if(!self->has_function) return NULL;
  121. Function* ud = py_touserdata(self->p0);
  122. if(ud->closure == NULL) return NULL;
  123. return NameDict__try_get(ud->closure, name);
  124. }
  125. int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
  126. int Frame__lineno(const Frame* self) {
  127. int ip = Frame__ip(self);
  128. return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
  129. }
  130. int Frame__iblock(const Frame* self) {
  131. int ip = Frame__ip(self);
  132. return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
  133. }
  134. py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) {
  135. assert(!self->is_dynamic);
  136. return FastLocals__try_get_by_name(self->locals, self->co, name);
  137. }