obj.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #include "safestl.h"
  3. struct CodeObject;
  4. struct Frame;
  5. struct BaseRef;
  6. class VM;
  7. typedef std::function<PyVar(VM*, const pkpy::Args&)> NativeFuncRaw;
  8. typedef pkpy::shared_ptr<CodeObject> CodeObject_;
  9. namespace pkpy{
  10. struct NativeFunc {
  11. NativeFuncRaw f;
  12. int argc; // DONOT include self
  13. bool method;
  14. NativeFunc(NativeFuncRaw f, int argc, bool method) : f(f), argc(argc), method(method) {}
  15. inline PyVar operator()(VM* vm, const pkpy::Args& args) const;
  16. };
  17. struct Function {
  18. Str name;
  19. CodeObject_ code;
  20. std::vector<Str> args;
  21. Str starredArg; // empty if no *arg
  22. pkpy::NameDict kwArgs; // empty if no k=v
  23. std::vector<Str> kwArgsOrder;
  24. bool hasName(const Str& val) const {
  25. bool _0 = std::find(args.begin(), args.end(), val) != args.end();
  26. bool _1 = starredArg == val;
  27. bool _2 = kwArgs.find(val) != kwArgs.end();
  28. return _0 || _1 || _2;
  29. }
  30. };
  31. struct BoundMethod {
  32. PyVar obj;
  33. PyVar method;
  34. };
  35. struct Range {
  36. i64 start = 0;
  37. i64 stop = -1;
  38. i64 step = 1;
  39. };
  40. struct Slice {
  41. int start = 0;
  42. int stop = 0x7fffffff;
  43. void normalize(int len){
  44. if(start < 0) start += len;
  45. if(stop < 0) stop += len;
  46. if(start < 0) start = 0;
  47. if(stop > len) stop = len;
  48. }
  49. };
  50. typedef shared_ptr<Function> Function_;
  51. }
  52. class BaseIter {
  53. protected:
  54. VM* vm;
  55. PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
  56. public:
  57. virtual PyVar next() = 0;
  58. PyVarRef var;
  59. BaseIter(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
  60. virtual ~BaseIter() = default;
  61. };
  62. struct PyObject {
  63. Type type;
  64. pkpy::NameDict* _attr;
  65. // void* _tid;
  66. const int _size;
  67. inline bool is_attr_valid() const noexcept { return _attr != nullptr; }
  68. inline pkpy::NameDict& attr() noexcept { return *_attr; }
  69. inline PyVar& attr(const Str& name) noexcept { return (*_attr)[name]; }
  70. inline bool is_type(Type type) const noexcept{ return this->type == type; }
  71. virtual void* value() = 0;
  72. PyObject(Type type, const int size) : type(type), _size(size) {}
  73. virtual ~PyObject() { delete _attr; }
  74. };
  75. template <typename T>
  76. struct Py_ : PyObject {
  77. T _value;
  78. Py_(Type type, T val) : PyObject(type, sizeof(Py_<T>)), _value(val) {
  79. if constexpr (std::is_same_v<T, Dummy> || std::is_same_v<T, Type>
  80. || std::is_same_v<T, pkpy::Function_> || std::is_same_v<T, pkpy::NativeFunc>) {
  81. _attr = new pkpy::NameDict();
  82. }else{
  83. _attr = nullptr;
  84. }
  85. }
  86. void* value() override { return &_value; }
  87. };
  88. #define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
  89. #define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attr(__name__))
  90. #define PY_CLASS(mod, name) \
  91. inline static Type _type(VM* vm) { return OBJ_GET(Type, vm->_modules[#mod]->attr(#name)); } \
  92. inline static const char* _mod() { return #mod; } \
  93. inline static const char* _name() { return #name; }
  94. namespace pkpy {
  95. template<int N>
  96. struct MemBlock {
  97. std::vector<void*> a;
  98. int block_size;
  99. MemBlock(int block_size) : block_size(block_size) {
  100. new_block();
  101. }
  102. void new_block(){
  103. int8_t* total = (int8_t*)malloc(N * block_size);
  104. for(int i = 0; i < block_size; ++i){
  105. a.push_back((void*)(total + i * N));
  106. }
  107. }
  108. inline void* alloc(){
  109. if(a.empty()) new_block();
  110. void* p = a.back();
  111. a.pop_back();
  112. return p;
  113. }
  114. inline void dealloc(void* p) noexcept{
  115. a.push_back(p);
  116. }
  117. ~MemBlock(){
  118. free(a[0]);
  119. }
  120. };
  121. constexpr int kMemObjSize = sizeof(int) + sizeof(Py_<i64>);
  122. static THREAD_LOCAL MemBlock<kMemObjSize> _mem_pool(512);
  123. template<>
  124. struct SpAllocator<PyObject> {
  125. template<typename U>
  126. inline static int* alloc(){
  127. if constexpr (sizeof(int) + sizeof(U) == kMemObjSize) {
  128. return (int*)_mem_pool.alloc();
  129. }
  130. return (int*)malloc(sizeof(int) + sizeof(U));
  131. }
  132. inline static void dealloc(int* counter){
  133. PyObject* obj = (PyObject*)(counter + 1);
  134. obj->~PyObject();
  135. if(obj->_size == kMemObjSize - sizeof(int)){
  136. _mem_pool.dealloc(counter);
  137. }else{
  138. free(counter);
  139. }
  140. }
  141. };
  142. }