obj.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #pragma once
  2. #include "common.h"
  3. #include "namedict.h"
  4. #include "tuplelist.h"
  5. namespace pkpy {
  6. struct CodeObject;
  7. struct Frame;
  8. struct Function;
  9. class VM;
  10. typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
  11. typedef shared_ptr<CodeObject> CodeObject_;
  12. struct NativeFunc {
  13. NativeFuncC f;
  14. int argc; // DONOT include self
  15. bool method;
  16. NativeFunc(NativeFuncC f, int argc, bool method) : f(f), argc(argc), method(method) {}
  17. PyObject* operator()(VM* vm, ArgsView args) const;
  18. };
  19. typedef void (*StackFuncC)(VM*);
  20. struct StackFunc {
  21. StackFuncC f;
  22. StackFunc(StackFuncC f) : f(f) {}
  23. void operator()(VM* vm) const;
  24. };
  25. struct FuncDecl {
  26. struct KwArg {
  27. int key; // index in co->varnames
  28. PyObject* value; // default value
  29. };
  30. CodeObject_ code; // code object of this function
  31. pod_vector<int> args; // indices in co->varnames
  32. int starred_arg = -1; // index in co->varnames, -1 if no *arg
  33. pod_vector<KwArg> kwargs; // indices in co->varnames
  34. bool nested = false; // whether this function is nested
  35. void _gc_mark() const;
  36. };
  37. using FuncDecl_ = shared_ptr<FuncDecl>;
  38. struct Function{
  39. FuncDecl_ decl;
  40. bool is_simple;
  41. PyObject* _module;
  42. NameDict_ _closure;
  43. };
  44. struct BoundMethod {
  45. PyObject* self;
  46. PyObject* func;
  47. BoundMethod(PyObject* self, PyObject* func) : self(self), func(func) {}
  48. };
  49. struct Range {
  50. i64 start = 0;
  51. i64 stop = -1;
  52. i64 step = 1;
  53. };
  54. struct Bytes{
  55. std::vector<char> _data;
  56. bool _ok;
  57. int size() const noexcept { return _data.size(); }
  58. int operator[](int i) const noexcept { return (int)(uint8_t)_data[i]; }
  59. const char* data() const noexcept { return _data.data(); }
  60. bool operator==(const Bytes& rhs) const noexcept {
  61. return _data == rhs._data;
  62. }
  63. bool operator!=(const Bytes& rhs) const noexcept {
  64. return _data != rhs._data;
  65. }
  66. std::string str() const noexcept { return std::string(_data.begin(), _data.end()); }
  67. Bytes() : _data(), _ok(false) {}
  68. Bytes(std::vector<char>&& data) : _data(std::move(data)), _ok(true) {}
  69. operator bool() const noexcept { return _ok; }
  70. };
  71. using Super = std::pair<PyObject*, Type>;
  72. struct Slice {
  73. PyObject* start;
  74. PyObject* stop;
  75. PyObject* step;
  76. Slice(PyObject* start, PyObject* stop, PyObject* step) : start(start), stop(stop), step(step) {}
  77. };
  78. class BaseIter {
  79. protected:
  80. VM* vm;
  81. public:
  82. BaseIter(VM* vm) : vm(vm) {}
  83. virtual PyObject* next() = 0;
  84. virtual ~BaseIter() = default;
  85. };
  86. struct GCHeader {
  87. bool enabled; // whether this object is managed by GC
  88. bool marked; // whether this object is marked
  89. GCHeader() : enabled(true), marked(false) {}
  90. };
  91. struct PyObject{
  92. GCHeader gc;
  93. Type type;
  94. NameDict* _attr;
  95. bool is_attr_valid() const noexcept { return _attr != nullptr; }
  96. NameDict& attr() noexcept { return *_attr; }
  97. PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; }
  98. virtual void* value() = 0;
  99. virtual void _obj_gc_mark() = 0;
  100. PyObject(Type type) : type(type), _attr(nullptr) {}
  101. virtual ~PyObject() {
  102. if(_attr == nullptr) return;
  103. _attr->~NameDict();
  104. pool64.dealloc(_attr);
  105. }
  106. void enable_instance_dict(float lf=kInstAttrLoadFactor) noexcept {
  107. _attr = new(pool64.alloc<NameDict>()) NameDict(lf);
  108. }
  109. };
  110. template <typename, typename=void> struct has_gc_marker : std::false_type {};
  111. template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
  112. template <typename T>
  113. struct Py_ final: PyObject {
  114. T _value;
  115. void* value() override { return &_value; }
  116. void _obj_gc_mark() override {
  117. if constexpr (has_gc_marker<T>::value) {
  118. _value._gc_mark();
  119. }
  120. }
  121. Py_(Type type, const T& value) : PyObject(type), _value(value) {}
  122. Py_(Type type, T&& value) : PyObject(type), _value(std::move(value)) {}
  123. };
  124. struct MappingProxy{
  125. PyObject* obj;
  126. MappingProxy(PyObject* obj) : obj(obj) {}
  127. NameDict& attr() noexcept { return obj->attr(); }
  128. };
  129. #define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
  130. // #define OBJ_GET(T, obj) (*reinterpret_cast<T*>((obj)->value()))
  131. #define OBJ_MARK(obj) \
  132. if(!is_tagged(obj) && !(obj)->gc.marked) { \
  133. (obj)->gc.marked = true; \
  134. (obj)->_obj_gc_mark(); \
  135. if((obj)->is_attr_valid()) gc_mark_namedict((obj)->attr()); \
  136. }
  137. inline void gc_mark_namedict(NameDict& t){
  138. if(t.size() == 0) return;
  139. for(uint16_t i=0; i<t._capacity; i++){
  140. if(t._items[i].first.empty()) continue;
  141. OBJ_MARK(t._items[i].second);
  142. }
  143. }
  144. Str obj_type_name(VM* vm, Type type);
  145. #if DEBUG_NO_BUILTIN_MODULES
  146. #define OBJ_NAME(obj) Str("<?>")
  147. #else
  148. #define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
  149. #endif
  150. const int kTpIntIndex = 2;
  151. const int kTpFloatIndex = 3;
  152. inline bool is_type(PyObject* obj, Type type) {
  153. #if DEBUG_EXTRA_CHECK
  154. if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr");
  155. if(is_special(obj)) throw std::runtime_error("is_type() called with special object");
  156. #endif
  157. switch(type.index){
  158. case kTpIntIndex: return is_int(obj);
  159. case kTpFloatIndex: return is_float(obj);
  160. default: return !is_tagged(obj) && obj->type == type;
  161. }
  162. }
  163. inline bool is_non_tagged_type(PyObject* obj, Type type) {
  164. #if DEBUG_EXTRA_CHECK
  165. if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr");
  166. if(is_special(obj)) throw std::runtime_error("is_non_tagged_type() called with special object");
  167. #endif
  168. return !is_tagged(obj) && obj->type == type;
  169. }
  170. union BitsCvt {
  171. i64 _int;
  172. f64 _float;
  173. BitsCvt(i64 val) : _int(val) {}
  174. BitsCvt(f64 val) : _float(val) {}
  175. };
  176. template <typename, typename=void> struct is_py_class : std::false_type {};
  177. template <typename T> struct is_py_class<T, std::void_t<decltype(T::_type)>> : std::true_type {};
  178. template<typename T> void _check_py_class(VM*, PyObject*);
  179. template<typename T> T py_pointer_cast(VM*, PyObject*);
  180. template<typename __T>
  181. __T py_cast(VM* vm, PyObject* obj) {
  182. using T = std::decay_t<__T>;
  183. if constexpr(std::is_pointer_v<T>){
  184. return py_pointer_cast<T>(vm, obj);
  185. }else if constexpr(is_py_class<T>::value){
  186. _check_py_class<T>(vm, obj);
  187. return OBJ_GET(T, obj);
  188. }else {
  189. return Discarded();
  190. }
  191. }
  192. template<typename __T>
  193. __T _py_cast(VM* vm, PyObject* obj) {
  194. using T = std::decay_t<__T>;
  195. if constexpr(std::is_pointer_v<__T>){
  196. return py_pointer_cast<__T>(vm, obj);
  197. }else if constexpr(is_py_class<T>::value){
  198. return OBJ_GET(T, obj);
  199. }else{
  200. return Discarded();
  201. }
  202. }
  203. #define VAR(x) py_var(vm, x)
  204. #define CAST(T, x) py_cast<T>(vm, x)
  205. #define _CAST(T, x) _py_cast<T>(vm, x)
  206. /*****************************************************************/
  207. template<>
  208. struct Py_<List> final: PyObject {
  209. List _value;
  210. void* value() override { return &_value; }
  211. Py_(Type type, List&& val): PyObject(type), _value(std::move(val)) {}
  212. Py_(Type type, const List& val): PyObject(type), _value(val) {}
  213. void _obj_gc_mark() override {
  214. for(PyObject* obj: _value) OBJ_MARK(obj);
  215. }
  216. };
  217. template<>
  218. struct Py_<Tuple> final: PyObject {
  219. Tuple _value;
  220. void* value() override { return &_value; }
  221. Py_(Type type, Tuple&& val): PyObject(type), _value(std::move(val)) {}
  222. Py_(Type type, const Tuple& val): PyObject(type), _value(val) {}
  223. void _obj_gc_mark() override {
  224. for(PyObject* obj: _value) OBJ_MARK(obj);
  225. }
  226. };
  227. template<>
  228. struct Py_<MappingProxy> final: PyObject {
  229. MappingProxy _value;
  230. void* value() override { return &_value; }
  231. Py_(Type type, MappingProxy val): PyObject(type), _value(val) {}
  232. void _obj_gc_mark() override {
  233. OBJ_MARK(_value.obj);
  234. }
  235. };
  236. template<>
  237. struct Py_<BoundMethod> final: PyObject {
  238. BoundMethod _value;
  239. void* value() override { return &_value; }
  240. Py_(Type type, BoundMethod val): PyObject(type), _value(val) {}
  241. void _obj_gc_mark() override {
  242. OBJ_MARK(_value.self);
  243. OBJ_MARK(_value.func);
  244. }
  245. };
  246. template<>
  247. struct Py_<Slice> final: PyObject {
  248. Slice _value;
  249. void* value() override { return &_value; }
  250. Py_(Type type, Slice val): PyObject(type), _value(val) {}
  251. void _obj_gc_mark() override {
  252. OBJ_MARK(_value.start);
  253. OBJ_MARK(_value.stop);
  254. OBJ_MARK(_value.step);
  255. }
  256. };
  257. template<>
  258. struct Py_<Function> final: PyObject {
  259. Function _value;
  260. void* value() override { return &_value; }
  261. Py_(Type type, Function val): PyObject(type), _value(val) {
  262. enable_instance_dict();
  263. }
  264. void _obj_gc_mark() override {
  265. _value.decl->_gc_mark();
  266. if(_value._module != nullptr) OBJ_MARK(_value._module);
  267. if(_value._closure != nullptr) gc_mark_namedict(*_value._closure);
  268. }
  269. };
  270. template<>
  271. struct Py_<NativeFunc> final: PyObject {
  272. NativeFunc _value;
  273. void* value() override { return &_value; }
  274. Py_(Type type, NativeFunc val): PyObject(type), _value(val) {
  275. enable_instance_dict();
  276. }
  277. void _obj_gc_mark() override {}
  278. };
  279. template<>
  280. struct Py_<Super> final: PyObject {
  281. Super _value;
  282. void* value() override { return &_value; }
  283. Py_(Type type, Super val): PyObject(type), _value(val) {}
  284. void _obj_gc_mark() override {
  285. OBJ_MARK(_value.first);
  286. }
  287. };
  288. template<>
  289. struct Py_<DummyInstance> final: PyObject {
  290. void* value() override { return nullptr; }
  291. Py_(Type type, DummyInstance val): PyObject(type) {
  292. enable_instance_dict();
  293. }
  294. void _obj_gc_mark() override {}
  295. };
  296. template<>
  297. struct Py_<Type> final: PyObject {
  298. Type _value;
  299. void* value() override { return &_value; }
  300. Py_(Type type, Type val): PyObject(type), _value(val) {
  301. enable_instance_dict(kTypeAttrLoadFactor);
  302. }
  303. void _obj_gc_mark() override {}
  304. };
  305. template<>
  306. struct Py_<DummyModule> final: PyObject {
  307. void* value() override { return nullptr; }
  308. Py_(Type type, DummyModule val): PyObject(type) {
  309. enable_instance_dict(kTypeAttrLoadFactor);
  310. }
  311. void _obj_gc_mark() override {}
  312. };
  313. } // namespace pkpy