trying not to leak memory

This commit is contained in:
FelixBrendel
2019-10-30 00:47:52 +01:00
parent 814cceaf3d
commit a790a38655
22 changed files with 204 additions and 78 deletions
+1 -1
Submodule 3rd/ftb updated: a20539587c...43da71f809
+4
View File
@@ -0,0 +1,4 @@
(define a 10)
(define (get-a-1)
a)
+8
View File
@@ -0,0 +1,8 @@
(import "import1.slime")
(define (set-a-2 s)
(set! a s))
(define (get-a-2)
a)
+1 -1
View File
@@ -88,7 +88,7 @@
(define (range (:from 0) :to) :doc "Returns a sequence of numbers starting with the number defined\nby the key =from= and ends with the number defined in =to=." (when (< from to) (pair from (range :from (+ 1 from) :to to))))
(define (range-while (:from 0) to) :doc "Returns a sequence of numbers starting with the number defined\nby the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (mutate from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (mutate from (increment from)))) result)
(define (range-while (:from 0) :to) :doc "Returns a sequence of numbers starting with the number defined\nby the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (set! from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (set! from (increment from)))) result)
(define (map fun seq) :doc "Takes a function and a sequence as arguments and returns a new\nsequence which contains the results of using the first sequences\nelemens as argument to that function." (if (null? seq) seq (pair (fun (first seq)) (map fun (rest seq)))))
BIN
View File
Binary file not shown.
+8 -8
View File
@@ -89,13 +89,13 @@
;; :key2 value2,
;; :key1 value1))
(assert (= (length (first p)) 6))
(assert (= (ds::plist::get p :key1) 'value4))
;; (assert (= (length (first p)) 6))
;; (assert (= (ds::plist::get p :key1) 'value4))
(ds::plist::remove! p :key1)
;; p == ((:key2 value2,
;; :key1 value1))
;; (ds::plist::remove! p :key1)
;; ;; p == ((:key2 value2,
;; ;; :key1 value1))
(assert (= (length (first p)) 4))
(assert (= (ds::plist::get p :key1) 'value1))
(assert (= (ds::plist::get p :key2) 'value2))
;; (assert (= (length (first p)) 4))
;; (assert (= (ds::plist::get p :key1) 'value1))
;; (assert (= (ds::plist::get p :key2) 'value2))
+17
View File
@@ -0,0 +1,17 @@
(import "import1.slime")
(assert (= a 10))
(assert (= (get-a-1) 10))
(import "import2.slime")
(assert (= a 10))
(assert (= (get-a-1) 10))
(assert (= (get-a-2) 10))
(set-a-2 11)
(assert (= a 11))
(assert (= (get-a-1) 11))
(assert (= (get-a-2) 11))
+7 -1
View File
@@ -7,7 +7,13 @@ set exeName=slime.exe
taskkill /F /IM %exeName% > NUL 2> NUL
echo ---------- Compiling ----------
call ..\timecmd cl ../src/main.cpp /D_PROFILING /D_DEBUG /D_DONT_BREAK_ON_ERRORS /Zi /std:c++latest /Fe%exeName% /W3 /wd4003 /nologo /EHsc /link /NODEFAULTLIB:libucrt libucrtd.lib
call ..\timecmd cl ^
../src/main.cpp ^
/I../3rd/ ^
/D_PROFILING /D_DEBUG /D_DONT_BREAK_ON_ERRORS ^
/Zi /std:c++latest /Fe%exeName% /W3 /wd4003 /nologo /EHsc ^
/link /NODEFAULTLIB:libucrt libucrtd.lib
rem call ..\timecmd clang-cl ../src/main.cpp -o %exeName% /O2 /std:c++latest /W3 /Zi /EHsc
if %errorlevel% == 0 (
+21
View File
@@ -128,3 +128,24 @@
#define in_caller_env fluid_let( \
Globals::Current_Execution::envi_stack.next_index, \
Globals::Current_Execution::envi_stack.next_index-1)
/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))
/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)
+5
View File
@@ -1,3 +1,5 @@
#pragma once
#include <functional>
#include "ftb/arraylist.hpp"
#include "ftb/hashmap.hpp"
@@ -182,11 +184,13 @@ namespace Slime {
void visualize_lisp_machine();
void generate_docs(String* path);
void log_error();
namespace Memory {
extern Lisp_Object* nil;
extern Lisp_Object* t;
Environment* create_child_environment(Environment* parent);
Environment* create_built_ins_environment();
Lisp_Object* create_lisp_object_cfunction(bool is_special);
Lisp_Object* get_or_create_lisp_object_keyword(const char* identifier);
@@ -196,6 +200,7 @@ namespace Slime {
void free_everything();
String* create_string(const char*);
Lisp_Object* create_lisp_object_number(double);
Lisp_Object* create_lisp_object_pointer(void*);
Lisp_Object* get_or_create_lisp_object_symbol(String* identifier);
Lisp_Object* get_or_create_lisp_object_symbol(const char*);
Lisp_Object* get_or_create_lisp_object_keyword(String* identifier);
+36
View File
@@ -0,0 +1,36 @@
* mallocs
|------------------------------------------+------------------------|
| location | always freed |
|------------------------------------------+------------------------|
| [[file:3rd\ftb\arraylist.hpp::11]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::17]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::44]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::46]]: | yes |
| [[file:.\src\io.cpp::49]]: | yes |
| [[file:.\src\io.cpp::164]]: | yes |
| [[file:.\src\io.cpp::209]]: | yes |
| [[file:.\src\io.cpp::285]]: | yes |
| [[file:.\src\memory.cpp::158]]: | yes in free_everything |
| [[file:.\src\platform.cpp::3]]: | yes |
| [[file:.\src\platform.cpp::27]]: | yes |
| [[file:.\src\platform.cpp::47]]: | yes |
| [[file:.\src\platform.cpp::81]]: | yes |
|------------------------------------------+------------------------|
* news
|----------------------------------+-------------------------------------------------------------------------------------|
| location | always deleted |
|----------------------------------+-------------------------------------------------------------------------------------|
| [[file:.\src\eval.cpp::262]]: | ::new (&(result->positional.symbols)) Array_List<Lisp_Object*>; |
| [[file:.\src\eval.cpp::263]]: | ::new (&(result->keyword.keywords)) Array_List<Lisp_Object*>; |
| [[file:.\src\eval.cpp:264]]: | ::new (&(result->keyword.values)) Array_List<Lisp_Object*>; |
| [[file:.\src\io.cpp:284]]: | // allocate a new block of memory size char (1 byte) instead of wide char (2 bytes) |
| [[file:.\src\io.cpp:306]]: | wchar_t* wc = new wchar_t[cSize]; |
| [[file:.\src\memory.cpp:336]]: | // node->value.lambdaWrapper = new Lambda_Wrapper(function); |
| [[file:.\src\memory.cpp:383]]: | // inject a new array list; |
| [[file:.\src\parse.cpp:195]]: | // better for keeping track of the encountered new lines and |
| [[file:.\src\parse.cpp:196]]: | // characters since last new line so we can update the parser |
| [[file:.\src\parse.cpp:208]]: | /* new col = (count chars since last \n) + 1 */ |
|----------------------------------+-------------------------------------------------------------------------------------|
+20 -8
View File
@@ -69,35 +69,47 @@ proc built_in_load(String* file_name) -> Lisp_Object* {
}
create_generic_error("The file to load '%s' was not found in the load path.",
Memory::get_c_str(file_name));
return nullptr;
}
}
Lisp_Object* result = Memory::nil;
Array_List<Lisp_Object*> program;
Array_List<Lisp_Object*>* program;
try program = Parser::parse_program(Memory::create_string(fullpath), file_content);
for (int i = 0; i < program.next_index; ++i) {
try result = eval_expr(program.data[i]);
for (int i = 0; i < program->next_index; ++i) {
try result = eval_expr(program->data[i]);
}
delete program;
return result;
}
proc built_in_import(String* file_name) -> Lisp_Object* {
// create new empty environment
Environment* new_env;
try new_env = Memory::create_child_environment(get_root_environment());
get_current_environment()->parents.append(new_env);
new_env = Memory::file_to_env_map.get_object(Memory::get_c_str(file_name));
if (!new_env) {
// create new empty environment
try new_env = Memory::create_child_environment(get_root_environment());
// TODO(Felix): check absoulute paths in the map, not just
// relative ones
Memory::file_to_env_map.set_object(Memory::get_c_str(file_name), new_env);
push_environment(new_env);
defer {
pop_environment();
};
Lisp_Object* res = built_in_load(file_name);
Lisp_Object* res;
try res = built_in_load(file_name);
}
return res;
get_current_environment()->parents.append(new_env);
return Memory::nil;
}
proc load_built_ins_into_environment() -> void {
+21
View File
@@ -128,3 +128,24 @@
#define in_caller_env fluid_let( \
Globals::Current_Execution::envi_stack.next_index, \
Globals::Current_Execution::envi_stack.next_index-1)
/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))
/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)
-35
View File
@@ -16,41 +16,6 @@
# define if_linux if constexpr (true)
#endif
/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))
/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)
/*
#define assert(cond) \
if_debug { \
if (!cond) { \
if (log_level == Log_Level::Debug) { \
printf("Assertion failed: %s %d", __FILE__, __LINE__); \
} \
debug_break(); \
} \
} else {} \
*/
#define console_normal "\x1B[0m"
#define console_red "\x1B[31m"
#define console_green "\x1B[32m"
+3 -3
View File
@@ -259,9 +259,9 @@ proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_O
result = &function->value.function.args;
}
::new (&(result->positional.symbols)) Array_List<Lisp_Object*>;
::new (&(result->keyword.keywords)) Array_List<Lisp_Object*>;
::new (&(result->keyword.values)) Array_List<Lisp_Object*>;
::new (&result->positional.symbols) Array_List<Lisp_Object*>;
::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
::new (&result->keyword.values) Array_List<Lisp_Object*>;
// first init the fields
// result->positional = create_positional_argument_list(16);
+3
View File
@@ -1,7 +1,10 @@
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
+6
View File
@@ -39,3 +39,9 @@ proc append_to_keyword_argument_list(Keyword_Arguments* args,
args->keywords.append(keyword);
args->values.append(default_value);
}
Lisp_Object::~Lisp_Object() {
if (Memory::get_type(this) == Lisp_Object_Type::HashMap) {
this->value.hashMap.~Hash_Map();
}
}
+3
View File
@@ -1,10 +1,13 @@
#include "libslime.cpp"
int main(int argc, char* argv[]) {
if (argc > 1) {
if (Slime::string_equal(argv[1], "--run-tests")) {
int res = Slime::run_all_tests();
// Slime::interprete_file((char*)"generate-docs.slime");
_CrtDumpMemoryLeaks();
return res ? 0 : 1;
}
+17 -5
View File
@@ -6,6 +6,8 @@ namespace Memory {
Hash_Map<char*, Lisp_Object*> global_symbol_table;
Hash_Map<char*, Lisp_Object*> global_keyword_table;
Hash_Map<char*, Environment*> file_to_env_map;
// ------------------
// lisp_objects
// ------------------
@@ -177,13 +179,23 @@ namespace Memory {
free_spots_in_string_memory.next_index = 0;
::new((&global_symbol_table)) Hash_Map<char*, Lisp_Object*>;
::new((&global_keyword_table)) Hash_Map<char*, Lisp_Object*>;
global_symbol_table.~Hash_Map();
global_keyword_table.~Hash_Map();
file_to_env_map.~Hash_Map();
::new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
::new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
::new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;
try_void Parser::standard_in = create_string("stdin");
object_memory.reset();
environment_memory.reset();
object_memory.~Bucket_Allocator();
// environment_memory.~Bucket_Allocator();
::new(&object_memory) Bucket_Allocator<Lisp_Object, 1024>;
::new(&environment_memory) Bucket_Allocator<Environment, 1024>;
next_free_spot_in_string_memory = string_memory;
@@ -404,7 +416,7 @@ namespace Memory {
try load_built_ins_into_environment();
built_in_load(Memory::create_string("pre.slime"));
try built_in_load(Memory::create_string("pre.slime"));
return ret;
}
+7 -8
View File
@@ -98,7 +98,6 @@ namespace Parser {
// get the atom
String* ret = Memory::create_string("", atom_length);
// char* atom = (char*)malloc(atom_length*sizeof(char)+1); // plus null char
strcpy(&ret->data, text+(*index_in_text));
// restore the original string
@@ -448,7 +447,7 @@ namespace Parser {
}
proc write_expanded_file(String* file_name, Array_List<Lisp_Object*> program) -> void {
proc write_expanded_file(String* file_name, Array_List<Lisp_Object*>* program) -> void {
const char* ext = ".expanded";
char* newName = (char*)calloc(10 + file_name->length, sizeof(char));
strcpy(newName, Memory::get_c_str(file_name));
@@ -465,21 +464,21 @@ namespace Parser {
exit(1);
}
for (int i = 0; i < program.next_index; ++i) {
for (int i = 0; i < program->next_index; ++i) {
// a macro will parse as nil for now, so we skip those
if (program.data[i] == Memory::nil)
if (program->data[i] == Memory::nil)
continue;
print(program.data[i], true, f);
print(program->data[i], true, f);
fprintf(f, "\n\n");
}
}
proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*> {
proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*>* {
parser_file = file_name;
parser_line = 1;
parser_col = 0;
Array_List<Lisp_Object*> program;
Array_List<Lisp_Object*>* program = new Array_List<Lisp_Object*>;
int index_in_text = 0;
@@ -490,7 +489,7 @@ namespace Parser {
try_struct {
parsed = parse_expression(text, &index_in_text);
}
program.append(parsed);
program->append(parsed);
} break;
case ';':
case ' ':
+8 -1
View File
@@ -103,6 +103,11 @@ struct Arguments {
struct Environment {
Array_List<Environment*> parents;
Hash_Map<void*, Lisp_Object*> hm;
~Environment() {
parents.~Array_List();
hm.~Hash_Map();
}
};
struct Function {
@@ -123,7 +128,7 @@ struct Lisp_Object {
u64 flags;
Lisp_Object* userType; // keyword
String* docstring;
union {
union value {
Symbol symbol; // used for symbols and keywords
double number;
String* string;
@@ -134,7 +139,9 @@ struct Lisp_Object {
void* pointer;
Continuation continuation;
Hash_Map<Lisp_Object*, Lisp_Object*> hashMap;
~value() {}
} value;
~Lisp_Object();
};
struct Error {
+2 -1
View File
@@ -596,7 +596,7 @@ proc test_file(const char* file) -> testresult {
pop_environment();
};
built_in_load(Memory::create_string(file));
try built_in_load(Memory::create_string(file));
assert_no_error();
return pass;
@@ -654,6 +654,7 @@ proc run_all_tests() -> bool {
invoke_test_script("automata");
invoke_test_script("sicp");
invoke_test_script("hashmaps");
invoke_test_script("singular_imports");
// Memory::print_status();