Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

543 строки
18 KiB

  1. namespace Slime::Memory {
  2. // ------------------
  3. // global symbol / keyword table
  4. // ------------------
  5. Hash_Map<char*, Lisp_Object*> global_symbol_table;
  6. Hash_Map<char*, Lisp_Object*> global_keyword_table;
  7. Hash_Map<char*, Environment*> file_to_env_map;
  8. // ------------------
  9. // lisp_objects
  10. // ------------------
  11. Bucket_Allocator<Lisp_Object> object_memory(1024, 8);
  12. // ------------------
  13. // environments
  14. // ------------------
  15. Bucket_Allocator<Environment> environment_memory(1024, 8);
  16. // ------------------
  17. // strings
  18. // ------------------
  19. int string_memory_size; // = 4096 * 1024; // == 98304kb == 96mb
  20. // free_spots_in_string_memory is an arraylist of pointers into
  21. // the string_memory, where dead String objects live (which give
  22. // information about their size)
  23. Array_List<void*> free_spots_in_string_memory;
  24. String* string_memory;
  25. String* next_free_spot_in_string_memory;
  26. // ------------------
  27. // immutables
  28. // ------------------
  29. Lisp_Object* nil = nullptr;
  30. Lisp_Object* t = nullptr;
  31. Lisp_Object* _if = nullptr;
  32. Lisp_Object* _define = nullptr;
  33. Lisp_Object* _begin = nullptr;
  34. proc print_status() {
  35. // printf("Memory Status:\n"
  36. // " - %f%% of the object_memory is used\n"
  37. // " - %d of %d total Lisp_Objects are in use\n"
  38. // " - %d holes in used memory (fragmentation)\n",
  39. // (1.0*next_index_in_object_memory - free_spots_in_object_memory.next_index)/object_memory_size,
  40. // next_index_in_object_memory - free_spots_in_object_memory.next_index, object_memory_size,
  41. // free_spots_in_object_memory.next_index);
  42. // printf("Memory Status:\n"
  43. // " - %f%% of the string_memory is used\n"
  44. // " - %d holes in used memory (fragmentation)\n",
  45. // (1.0*(size_t)next_free_spot_in_string_memory - (size_t)string_memory)/string_memory_size,
  46. // free_spots_in_string_memory.next_index);
  47. }
  48. inline proc get_c_str(String* str) -> char* {
  49. return &str->data;
  50. }
  51. inline proc get_c_str(Lisp_Object* str) -> char* {
  52. assert_type(str, Lisp_Object_Type::String);
  53. return get_c_str(str->value.string);
  54. }
  55. inline proc get_type(Lisp_Object* node) -> Lisp_Object_Type {
  56. // the type is in the bits 0 to 5 (including)
  57. return (Lisp_Object_Type) ((u64)node->flags & (u64)0b11111);
  58. }
  59. inline proc set_type(Lisp_Object* node, Lisp_Object_Type type) {
  60. // the type is in the bits 0 to 5 (including)
  61. u64 bitmask = (u64)-1;
  62. bitmask -= 0b11111;
  63. bitmask += (u64) type;
  64. node->flags = (u64)(node->flags) | bitmask;
  65. }
  66. proc hash(String* str) -> u64 {
  67. // TODO(Felix): When parsing symbols or keywords, compute the
  68. // hash while reading them in.
  69. u64 value = str->data << 7;
  70. for (int i = 1; i < str->length; ++i) {
  71. char c = ((char*)&str->data)[i];
  72. value = (1000003 * value) ^ c;
  73. }
  74. value ^= str->length;
  75. return value;
  76. }
  77. proc create_string(const char* str, int len) -> String* {
  78. // TODO(Felix): check the holes first, not just always append
  79. // at the end
  80. String* ret = next_free_spot_in_string_memory;
  81. ret->length = len;
  82. strcpy(&ret->data, str);
  83. // now update the next_free_spot_in_string_memory pointer:
  84. // overstrep the counter and the first char (thik of it as if
  85. // we were overstepping the last ('\0') char) and then we only
  86. // need to overstep 'len' more chars
  87. next_free_spot_in_string_memory += 1;
  88. // overstep the other chars
  89. next_free_spot_in_string_memory = ((String*)((char*)next_free_spot_in_string_memory)+len);
  90. return ret;
  91. }
  92. proc delete_string(String* str) {
  93. free_spots_in_string_memory.append((void*)str);
  94. }
  95. proc duplicate_string(String* str) -> String* {
  96. return create_string(get_c_str(str), str->length);
  97. }
  98. proc create_string (const char* str) -> String* {
  99. return create_string(str, (int)strlen(str));
  100. }
  101. proc create_lisp_object() -> Lisp_Object* {
  102. Lisp_Object* object = object_memory.allocate();
  103. object->flags = 0;
  104. object->sourceCodeLocation = nullptr;
  105. object->userType = nullptr;
  106. object->docstring = nullptr;
  107. return object;
  108. }
  109. proc free_everything() -> void {
  110. free(string_memory);
  111. object_memory.for_each([](Lisp_Object* lo){
  112. lo->~Lisp_Object();
  113. });
  114. environment_memory.for_each([](Environment* env){
  115. env->parents.dealloc();
  116. env->~Environment();
  117. });
  118. // free the exe dir:
  119. free(Globals::load_path.data[0]);
  120. Globals::load_path.dealloc();
  121. // Globals::Current_Execution::call_stack.dealloc();
  122. Globals::Current_Execution::envi_stack.dealloc();
  123. Globals::Current_Execution::cs.dealloc();
  124. Globals::Current_Execution::ams.dealloc();
  125. Globals::Current_Execution::pcs.dealloc();
  126. }
  127. proc create_child_environment(Environment* parent) -> Environment* {
  128. Environment* env = environment_memory.allocate();
  129. // inject a new array list;
  130. env->parents.alloc();
  131. if (parent)
  132. env->parents.append(parent);
  133. new(&env->hm) Hash_Map<void*, Lisp_Object*>;
  134. return env;
  135. }
  136. proc create_empty_environment() -> Environment* {
  137. Environment* ret;
  138. try ret = create_child_environment(nullptr);
  139. return ret;
  140. }
  141. proc init(int sms) -> void {
  142. profile_this();
  143. char* exe_path = get_exe_dir();
  144. // don't free exe path because it will be used until end of time
  145. Globals::load_path.alloc();
  146. // Globals::Current_Execution::call_stack.alloc();
  147. Globals::Current_Execution::envi_stack.alloc();
  148. Globals::Current_Execution::cs.alloc();
  149. Globals::Current_Execution::pcs.alloc();
  150. Globals::Current_Execution::ams.alloc();
  151. add_to_load_path(exe_path);
  152. add_to_load_path("../bin/");
  153. string_memory_size = sms;
  154. string_memory = (String*)malloc(string_memory_size * sizeof(char));
  155. next_free_spot_in_string_memory = string_memory;
  156. // init nil
  157. try_void nil = create_lisp_object();
  158. set_type(nil, Lisp_Object_Type::Nil);
  159. // init t
  160. try_void t = create_lisp_object();
  161. set_type(t, Lisp_Object_Type::T);
  162. try_void Parser::standard_in = create_string("stdin");
  163. Globals::Current_Execution::envi_stack.next_index = 0;
  164. Environment* env;
  165. try_void env = create_built_ins_environment();
  166. push_environment(env);
  167. Environment* user_env;
  168. try_void user_env = Memory::create_child_environment(env);
  169. push_environment(user_env);
  170. try_void _if = lookup_symbol(get_symbol("if"), env);
  171. try_void _define = lookup_symbol(get_symbol("define"), env);
  172. try_void _begin = lookup_symbol(get_symbol("begin"), env);
  173. }
  174. proc reset() -> void {
  175. profile_this();
  176. free_spots_in_string_memory.next_index = 0;
  177. global_symbol_table.~Hash_Map();
  178. global_keyword_table.~Hash_Map();
  179. file_to_env_map.~Hash_Map();
  180. new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
  181. new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
  182. new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;
  183. try_void Parser::standard_in = create_string("stdin");
  184. object_memory.for_each([](Lisp_Object* lo){
  185. lo->~Lisp_Object();
  186. });
  187. environment_memory.for_each([](Environment* env){
  188. env->~Environment();
  189. });
  190. object_memory.~Bucket_Allocator();
  191. environment_memory.~Bucket_Allocator();
  192. new(&object_memory) Bucket_Allocator<Lisp_Object>(1024, 8);
  193. new(&environment_memory) Bucket_Allocator<Environment>(1024, 8);
  194. next_free_spot_in_string_memory = string_memory;
  195. // init nil
  196. try_void nil = create_lisp_object();
  197. set_type(nil, Lisp_Object_Type::Nil);
  198. // init t
  199. try_void t = create_lisp_object();
  200. set_type(t, Lisp_Object_Type::T);
  201. Globals::Current_Execution::envi_stack.next_index = 0;
  202. Environment* env;
  203. try_void env = create_built_ins_environment();
  204. push_environment(env);
  205. Environment* user_env;
  206. try_void user_env = Memory::create_child_environment(env);
  207. push_environment(user_env);
  208. try_void _if = lookup_symbol(get_symbol("if"), env);
  209. try_void _define = lookup_symbol(get_symbol("define"), env);
  210. try_void _begin = lookup_symbol(get_symbol("begin"), env);
  211. }
  212. proc create_lisp_object(void* ptr) -> Lisp_Object* {
  213. Lisp_Object* node;
  214. try node = create_lisp_object();
  215. set_type(node, Lisp_Object_Type::Pointer);
  216. node->value.pointer = ptr;
  217. return node;
  218. }
  219. proc create_lisp_object_hash_map() -> Lisp_Object* {
  220. Lisp_Object* node;
  221. try node = create_lisp_object();
  222. set_type(node, Lisp_Object_Type::HashMap);
  223. node->value.hashMap = new Hash_Map<Lisp_Object*, Lisp_Object*>;
  224. return node;
  225. }
  226. proc create_lisp_object(double number) -> Lisp_Object* {
  227. Lisp_Object* node;
  228. try node = create_lisp_object();
  229. set_type(node, Lisp_Object_Type::Number);
  230. node->value.number = number;
  231. return node;
  232. }
  233. proc create_lisp_object(String* str) -> Lisp_Object* {
  234. Lisp_Object* node;
  235. try node = create_lisp_object();
  236. set_type(node, Lisp_Object_Type::String);
  237. node->value.string = str;
  238. return node;
  239. }
  240. proc create_lisp_object(const char* str) -> Lisp_Object* {
  241. Lisp_Object* node;
  242. try node = create_lisp_object();
  243. set_type(node, Lisp_Object_Type::String);
  244. node->value.string = create_string(str);
  245. return node;
  246. }
  247. proc allocate_vector(int size) -> Lisp_Object* {
  248. Lisp_Object* ret = object_memory.allocate(size);
  249. if (!ret) {
  250. create_out_of_memory_error("The vector is too big to fit in a memory bucket.");
  251. return nullptr;
  252. }
  253. return ret;
  254. }
  255. proc create_lisp_object_vector(int length, Lisp_Object* element_list) -> Lisp_Object* {
  256. try assert_type(element_list, Lisp_Object_Type::Pair);
  257. Lisp_Object* node;
  258. try node = create_lisp_object();
  259. set_type(node, Lisp_Object_Type::Vector);
  260. node->value.vector.length = length;
  261. try node->value.vector.data = allocate_vector(length);
  262. Lisp_Object* head = element_list;
  263. int i = 0;
  264. while (head != Memory::nil) {
  265. node->value.vector.data[i] = *head->value.pair.first;
  266. head = head->value.pair.rest;
  267. ++i;
  268. }
  269. return node;
  270. }
  271. proc create_lisp_object_vector(Lisp_Object* e1) -> Lisp_Object* {
  272. Lisp_Object* node;
  273. try node = create_lisp_object();
  274. set_type(node, Lisp_Object_Type::Vector);
  275. node->value.vector.length = 1;
  276. try node->value.vector.data = allocate_vector(1);
  277. node->value.vector.data[0] = *e1;
  278. return node;
  279. }
  280. proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2) -> Lisp_Object* {
  281. Lisp_Object* node;
  282. try node = create_lisp_object();
  283. set_type(node, Lisp_Object_Type::Vector);
  284. node->value.vector.length = 2;
  285. try node->value.vector.data = allocate_vector(2);
  286. node->value.vector.data[0] = *e1;
  287. node->value.vector.data[1] = *e2;
  288. return node;
  289. }
  290. proc create_lisp_object_vector(Lisp_Object* e1, Lisp_Object* e2, Lisp_Object* e3) -> Lisp_Object* {
  291. Lisp_Object* node;
  292. try node = create_lisp_object();
  293. set_type(node, Lisp_Object_Type::Vector);
  294. node->value.vector.length = 3;
  295. try node->value.vector.data = allocate_vector(3);
  296. node->value.vector.data[0] = *e1;
  297. node->value.vector.data[1] = *e2;
  298. node->value.vector.data[2] = *e3;
  299. return node;
  300. }
  301. proc get_symbol(String* identifier) -> Lisp_Object* {
  302. Lisp_Object* node = global_symbol_table.get_object(get_c_str(identifier));
  303. if (node)
  304. return (Lisp_Object*)node;
  305. try node = create_lisp_object();
  306. set_type(node, Lisp_Object_Type::Symbol);
  307. node->value.symbol = identifier;
  308. global_symbol_table.set_object(get_c_str(identifier), node);
  309. return node;
  310. }
  311. proc get_symbol(const char* identifier) -> Lisp_Object* {
  312. if (auto ret = global_symbol_table.get_object((char*)identifier))
  313. return (Lisp_Object*)ret;
  314. else {
  315. String* str;
  316. try str = Memory::create_string(identifier);
  317. return get_symbol(str);
  318. }
  319. }
  320. proc get_keyword(String* keyword) -> Lisp_Object* {
  321. Lisp_Object* node = global_keyword_table.get_object(get_c_str(keyword));
  322. if (node)
  323. return (Lisp_Object*)node;
  324. try node = create_lisp_object();
  325. set_type(node, Lisp_Object_Type::Keyword);
  326. node->value.symbol = keyword;
  327. global_keyword_table.set_object(get_c_str(keyword), node);
  328. return node;
  329. }
  330. proc get_keyword(const char* keyword) -> Lisp_Object* {
  331. if (auto ret = global_keyword_table.get_object((char*)keyword))
  332. return (Lisp_Object*)ret;
  333. else {
  334. String* str;
  335. try str = Memory::create_string(keyword);
  336. return get_keyword(str);
  337. }
  338. }
  339. proc create_lisp_object_cfunction(C_Function_Type type) -> Lisp_Object* {
  340. Lisp_Object* node;
  341. try node = create_lisp_object();
  342. set_type(node, Lisp_Object_Type::Function);
  343. node->value.function = (Function*)malloc(sizeof(Function));
  344. node->value.function->type.c_function_type = type;
  345. node->value.function->args.keyword.keywords.alloc();
  346. node->value.function->args.keyword.values.alloc();
  347. node->value.function->args.positional.symbols.alloc();
  348. node->value.function->is_c = true;
  349. return node;
  350. }
  351. proc create_lisp_object_function(Lisp_Function_Type ft) -> Lisp_Object* {
  352. Lisp_Object* func;
  353. try func = Memory::create_lisp_object();
  354. Memory::set_type(func, Lisp_Object_Type::Function);
  355. func->value.function = (Function*)malloc(sizeof(Function));
  356. func->value.function->args.keyword.keywords.alloc();
  357. func->value.function->args.keyword.values.alloc();
  358. func->value.function->args.positional.symbols.alloc();
  359. func->value.function->type.lisp_function_type = ft;
  360. func->value.function->is_c = false;
  361. return func;
  362. }
  363. proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* {
  364. Lisp_Object* node;
  365. try node = create_lisp_object();
  366. set_type(node, Lisp_Object_Type::Pair);
  367. // node->value.pair = new(Pair);
  368. node->value.pair.first = first;
  369. node->value.pair.rest = rest;
  370. return node;
  371. }
  372. proc copy_lisp_object(Lisp_Object* n) -> Lisp_Object* {
  373. // TODO(Felix): If argument is a list (pair), do a FULL copy,
  374. // we don't copy singleton objects
  375. if (n == Memory::nil || n == Memory::t ||
  376. Memory::get_type(n) == Lisp_Object_Type::Symbol ||
  377. Memory::get_type(n) == Lisp_Object_Type::Keyword ||
  378. Memory::get_type(n) == Lisp_Object_Type::Function)
  379. {
  380. return n;
  381. }
  382. Lisp_Object* target;
  383. try target = create_lisp_object();
  384. *target = *n;
  385. return target;
  386. }
  387. proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* {
  388. if (get_type(n) == Lisp_Object_Type::Pair)
  389. return n;
  390. return copy_lisp_object(n);
  391. }
  392. proc create_built_ins_environment() -> Environment* {
  393. Environment* ret;
  394. try ret = create_empty_environment();
  395. push_environment(ret);
  396. defer {
  397. pop_environment();
  398. };
  399. try load_built_ins_into_environment();
  400. try built_in_load(Memory::create_string("pre.slime"));
  401. return ret;
  402. }
  403. inline proc create_list(Lisp_Object* o1) -> Lisp_Object* {
  404. Lisp_Object* ret;
  405. try ret = create_lisp_object_pair(o1, nil);
  406. return ret;
  407. }
  408. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2) -> Lisp_Object* {
  409. Lisp_Object* ret;
  410. try ret = create_lisp_object_pair(o1, create_list(o2));
  411. return ret;
  412. }
  413. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3) -> Lisp_Object* {
  414. Lisp_Object* ret;
  415. try ret = create_lisp_object_pair(o1, create_list(o2, o3));
  416. return ret;
  417. }
  418. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4) -> Lisp_Object* {
  419. Lisp_Object* ret;
  420. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4));
  421. return ret;
  422. }
  423. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5) -> Lisp_Object* {
  424. Lisp_Object* ret;
  425. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4, o5));
  426. return ret;
  427. }
  428. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5, Lisp_Object* o6) -> Lisp_Object* {
  429. Lisp_Object* ret;
  430. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4, o5, o6));
  431. return ret;
  432. }
  433. }