/vm/layouts.hpp

http://github.com/abeaumont/factor · C++ Header · 382 lines · 266 code · 60 blank · 56 comment · 6 complexity · c8377804f65d3c86babb96673e689783 MD5 · raw file

  1. namespace factor
  2. {
  3. typedef unsigned char u8;
  4. typedef unsigned short u16;
  5. typedef unsigned int u32;
  6. typedef unsigned long long u64;
  7. typedef signed char s8;
  8. typedef signed short s16;
  9. typedef signed int s32;
  10. typedef signed long long s64;
  11. #ifdef _WIN64
  12. typedef long long fixnum;
  13. typedef unsigned long long cell;
  14. #else
  15. typedef long fixnum;
  16. typedef unsigned long cell;
  17. #endif
  18. inline static cell align(cell a, cell b)
  19. {
  20. return (a + (b-1)) & ~(b-1);
  21. }
  22. inline static cell alignment_for(cell a, cell b)
  23. {
  24. return align(a,b) - a;
  25. }
  26. static const cell data_alignment = 16;
  27. #define WORD_SIZE (signed)(sizeof(cell)*8)
  28. #define TAG_MASK 15
  29. #define TAG_BITS 4
  30. #define TAG(x) ((cell)(x) & TAG_MASK)
  31. #define UNTAG(x) ((cell)(x) & ~TAG_MASK)
  32. #define RETAG(x,tag) (UNTAG(x) | (tag))
  33. /*** Tags ***/
  34. #define FIXNUM_TYPE 0
  35. #define F_TYPE 1
  36. #define ARRAY_TYPE 2
  37. #define FLOAT_TYPE 3
  38. #define QUOTATION_TYPE 4
  39. #define BIGNUM_TYPE 5
  40. #define ALIEN_TYPE 6
  41. #define TUPLE_TYPE 7
  42. #define WRAPPER_TYPE 8
  43. #define BYTE_ARRAY_TYPE 9
  44. #define CALLSTACK_TYPE 10
  45. #define STRING_TYPE 11
  46. #define WORD_TYPE 12
  47. #define DLL_TYPE 13
  48. #define TYPE_COUNT 14
  49. static inline const char *type_name(cell type)
  50. {
  51. switch (type)
  52. {
  53. case FIXNUM_TYPE:
  54. return "fixnum";
  55. case F_TYPE:
  56. return "f";
  57. case ARRAY_TYPE:
  58. return "array";
  59. case FLOAT_TYPE:
  60. return "float";
  61. case QUOTATION_TYPE:
  62. return "quotation";
  63. case BIGNUM_TYPE:
  64. return "bignum";
  65. case ALIEN_TYPE:
  66. return "alien";
  67. case TUPLE_TYPE:
  68. return "tuple";
  69. case WRAPPER_TYPE:
  70. return "wrapper";
  71. case BYTE_ARRAY_TYPE:
  72. return "byte-array";
  73. case CALLSTACK_TYPE:
  74. return "callstack";
  75. case STRING_TYPE:
  76. return "string";
  77. case WORD_TYPE:
  78. return "word";
  79. case DLL_TYPE:
  80. return "dll";
  81. default:
  82. FACTOR_ASSERT(false);
  83. return "";
  84. }
  85. }
  86. enum code_block_type
  87. {
  88. code_block_unoptimized,
  89. code_block_optimized,
  90. code_block_pic
  91. };
  92. /* Constants used when floating-point trap exceptions are thrown */
  93. enum
  94. {
  95. FP_TRAP_INVALID_OPERATION = 1 << 0,
  96. FP_TRAP_OVERFLOW = 1 << 1,
  97. FP_TRAP_UNDERFLOW = 1 << 2,
  98. FP_TRAP_ZERO_DIVIDE = 1 << 3,
  99. FP_TRAP_INEXACT = 1 << 4,
  100. };
  101. /* What Factor calls 'f' */
  102. static const cell false_object = F_TYPE;
  103. inline static bool immediate_p(cell obj)
  104. {
  105. /* We assume that fixnums have tag 0 and false_object has tag 1 */
  106. return TAG(obj) <= F_TYPE;
  107. }
  108. inline static fixnum untag_fixnum(cell tagged)
  109. {
  110. #ifdef FACTOR_DEBUG
  111. FACTOR_ASSERT(TAG(tagged) == FIXNUM_TYPE);
  112. #endif
  113. return ((fixnum)tagged) >> TAG_BITS;
  114. }
  115. inline static cell tag_fixnum(fixnum untagged)
  116. {
  117. return RETAG(untagged << TAG_BITS,FIXNUM_TYPE);
  118. }
  119. #define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
  120. struct object {
  121. NO_TYPE_CHECK;
  122. cell header;
  123. cell size() const;
  124. template<typename Fixup> cell size(Fixup fixup) const;
  125. cell binary_payload_start() const;
  126. template<typename Fixup> cell binary_payload_start(Fixup fixup) const;
  127. cell *slots() const { return (cell *)this; }
  128. template<typename Iterator> void each_slot(Iterator &iter);
  129. /* Only valid for objects in tenured space; must cast to free_heap_block
  130. to do anything with it if its free */
  131. bool free_p() const
  132. {
  133. return (header & 1) == 1;
  134. }
  135. cell type() const
  136. {
  137. return (header >> 2) & TAG_MASK;
  138. }
  139. void initialize(cell type)
  140. {
  141. header = type << 2;
  142. }
  143. cell hashcode() const
  144. {
  145. return (header >> 6);
  146. }
  147. void set_hashcode(cell hashcode)
  148. {
  149. header = (header & 0x3f) | (hashcode << 6);
  150. }
  151. bool forwarding_pointer_p() const
  152. {
  153. return (header & 2) == 2;
  154. }
  155. object *forwarding_pointer() const
  156. {
  157. return (object *)UNTAG(header);
  158. }
  159. void forward_to(object *pointer)
  160. {
  161. header = ((cell)pointer | 2);
  162. }
  163. };
  164. /* Assembly code makes assumptions about the layout of this struct */
  165. struct array : public object {
  166. static const cell type_number = ARRAY_TYPE;
  167. static const cell element_size = sizeof(cell);
  168. /* tagged */
  169. cell capacity;
  170. cell *data() const { return (cell *)(this + 1); }
  171. };
  172. /* These are really just arrays, but certain elements have special
  173. significance */
  174. struct tuple_layout : public array {
  175. NO_TYPE_CHECK;
  176. /* tagged */
  177. cell klass;
  178. /* tagged fixnum */
  179. cell size;
  180. /* tagged fixnum */
  181. cell echelon;
  182. };
  183. struct bignum : public object {
  184. static const cell type_number = BIGNUM_TYPE;
  185. static const cell element_size = sizeof(cell);
  186. /* tagged */
  187. cell capacity;
  188. cell *data() const { return (cell *)(this + 1); }
  189. };
  190. struct byte_array : public object {
  191. static const cell type_number = BYTE_ARRAY_TYPE;
  192. static const cell element_size = 1;
  193. /* tagged */
  194. cell capacity;
  195. #ifndef FACTOR_64
  196. cell padding0;
  197. cell padding1;
  198. #endif
  199. template<typename Scalar> Scalar *data() const { return (Scalar *)(this + 1); }
  200. };
  201. /* Assembly code makes assumptions about the layout of this struct */
  202. struct string : public object {
  203. static const cell type_number = STRING_TYPE;
  204. /* tagged num of chars */
  205. cell length;
  206. /* tagged */
  207. cell aux;
  208. /* tagged */
  209. cell hashcode;
  210. u8 *data() const { return (u8 *)(this + 1); }
  211. };
  212. struct code_block;
  213. /* Assembly code makes assumptions about the layout of this struct:
  214. basis/bootstrap/images/images.factor
  215. basis/compiler/constants/constants.factor
  216. core/bootstrap/primitives.factor
  217. */
  218. struct word : public object {
  219. static const cell type_number = WORD_TYPE;
  220. /* TAGGED hashcode */
  221. cell hashcode;
  222. /* TAGGED word name */
  223. cell name;
  224. /* TAGGED word vocabulary */
  225. cell vocabulary;
  226. /* TAGGED definition */
  227. cell def;
  228. /* TAGGED property assoc for library code */
  229. cell props;
  230. /* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
  231. cell pic_def;
  232. /* TAGGED alternative entry point for direct tail calls. Used for inline caching */
  233. cell pic_tail_def;
  234. /* TAGGED machine code for sub-primitive */
  235. cell subprimitive;
  236. /* UNTAGGED entry point: jump here to execute word */
  237. void *entry_point;
  238. /* UNTAGGED compiled code block */
  239. /* defined in code_blocks.hpp */
  240. code_block *code() const;
  241. };
  242. /* Assembly code makes assumptions about the layout of this struct */
  243. struct wrapper : public object {
  244. static const cell type_number = WRAPPER_TYPE;
  245. cell object;
  246. };
  247. /* Assembly code makes assumptions about the layout of this struct */
  248. struct boxed_float : object {
  249. static const cell type_number = FLOAT_TYPE;
  250. #ifndef FACTOR_64
  251. cell padding;
  252. #endif
  253. double n;
  254. };
  255. /* Assembly code makes assumptions about the layout of this struct:
  256. basis/bootstrap/images/images.factor
  257. basis/compiler/constants/constants.factor
  258. core/bootstrap/primitives.factor
  259. */
  260. struct quotation : public object {
  261. static const cell type_number = QUOTATION_TYPE;
  262. /* tagged */
  263. cell array;
  264. /* tagged */
  265. cell cached_effect;
  266. /* tagged */
  267. cell cache_counter;
  268. /* UNTAGGED entry point; jump here to call quotation */
  269. void *entry_point;
  270. /* defined in code_blocks.hpp */
  271. code_block *code() const;
  272. };
  273. /* Assembly code makes assumptions about the layout of this struct */
  274. struct alien : public object {
  275. static const cell type_number = ALIEN_TYPE;
  276. /* tagged */
  277. cell base;
  278. /* tagged */
  279. cell expired;
  280. /* untagged */
  281. cell displacement;
  282. /* untagged */
  283. cell address;
  284. void update_address()
  285. {
  286. if(base == false_object)
  287. address = displacement;
  288. else
  289. address = UNTAG(base) + sizeof(byte_array) + displacement;
  290. }
  291. };
  292. struct dll : public object {
  293. static const cell type_number = DLL_TYPE;
  294. /* tagged byte array holding a C string */
  295. cell path;
  296. /* OS-specific handle */
  297. void *handle;
  298. };
  299. struct callstack : public object {
  300. static const cell type_number = CALLSTACK_TYPE;
  301. /* tagged */
  302. cell length;
  303. void *frame_top_at(cell offset) const
  304. {
  305. return (void *)((char *)(this + 1) + offset);
  306. }
  307. void *top() const { return (void *)(this + 1); }
  308. void *bottom() const { return (void *)((cell)(this + 1) + untag_fixnum(length)); }
  309. };
  310. struct tuple : public object {
  311. static const cell type_number = TUPLE_TYPE;
  312. /* tagged layout */
  313. cell layout;
  314. cell *data() const { return (cell *)(this + 1); }
  315. };
  316. struct data_root_range {
  317. cell *start;
  318. cell len;
  319. explicit data_root_range(cell *start_, cell len_) :
  320. start(start_), len(len_) {}
  321. };
  322. }