add clang-format; reformat files

This commit is contained in:
danyaberezun 2023-05-31 11:01:11 +02:00
parent f20d351dd0
commit ccd04c2159
10 changed files with 1885 additions and 1837 deletions

144
runtime/.clang-format Normal file
View file

@ -0,0 +1,144 @@
# Common settings
BasedOnStyle: LLVM
TabWidth: 2
IndentWidth: 2
UseTab: Never
ColumnLimit: 100
IndentCaseLabels: true
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
---
Language: Cpp
DisableFormat: false
Standard: Cpp11
AccessModifierOffset: -4
AlignAfterOpenBracket: true
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: true
BitFieldColonSpacing: Both
# Configure each individual brace in BraceWrapping
BreakBeforeBraces: Attach
# Control of individual brace wrapping cases
BraceWrapping: {
AfterClass: 'true'
AfterControlStatement: 'true'
AfterEnum : 'true'
AfterFunction : 'true'
AfterNamespace : 'true'
AfterStruct : 'true'
AfterUnion : 'true'
BeforeCatch : 'true'
BeforeElse : 'true'
IndentBraces : 'false'
AfterExternBlock : 'true'
SplitEmptyFunction : 'false'
SplitEmptyRecord : 'false'
SplitEmptyNamespace : 'true'
}
BreakAfterJavaFieldAnnotations: true
BreakBeforeInheritanceComma: false
BreakArrays: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakStringLiterals: true
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
SpaceBeforeCpp11BracedList: false
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentCaseLabels: true
FixNamespaceComments: true
IndentWrappedFunctionNames: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
JavaScriptQuotes: Double
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: Custom
SpaceBeforeParensOptions: {
AfterControlStatements: 'true'
AfterForeachMacros: 'true'
AfterFunctionDeclarationName: 'true'
AfterFunctionDefinitionName: 'true'
AfterIfMacros: 'true'
AfterOverloadedOperator: 'true'
AfterRequiresInClause: 'true'
AfterRequiresInExpression: 'true'
BeforeNonEmptyParentheses: 'false'
}
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 3
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceAfterTemplateKeyword: true
SpaceBeforeInheritanceColon: true
VerilogBreakBetweenInstancePorts: true
SortUsingDeclarations: true
SortIncludes: CaseInsensitive
IndentGotoLabels: false
InsertBraces: false
InsertNewlineAtEOF: true
# Comments are for developers, they should arrange them
ReflowComments: false
IncludeBlocks: Regroup
IndentPPDirectives: AfterHash
SeparateDefinitionBlocks: Always
IntegerLiteralSeparator:
Binary: 4
Decimal: 0
Hex: 0
---

View file

@ -1,18 +1,18 @@
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
#include "gc.h" #include "gc.h"
#include "runtime_common.h" #include "runtime_common.h"
#include <assert.h>
#include <execinfo.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h>
#include <sys/mman.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <sys/mman.h>
#include <time.h>
#include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <execinfo.h>
static const size_t INIT_HEAP_SIZE = MINIMUM_HEAP_CAPACITY; static const size_t INIT_HEAP_SIZE = MINIMUM_HEAP_CAPACITY;
@ -91,18 +91,16 @@ void compact_phase(size_t additional_size) {
size_t live_size = compute_locations(); size_t live_size = compute_locations();
// all in words // all in words
size_t next_heap_size = MAX(live_size * EXTRA_ROOM_HEAP_COEFFICIENT + additional_size, MINIMUM_HEAP_CAPACITY); size_t next_heap_size =
size_t next_heap_pseudo_size = MAX(next_heap_size, heap.size); // this is weird but here is why it happens: MAX(live_size * EXTRA_ROOM_HEAP_COEFFICIENT + additional_size, MINIMUM_HEAP_CAPACITY);
size_t next_heap_pseudo_size =
MAX(next_heap_size, heap.size); // this is weird but here is why it happens:
// if we allocate too little heap right now, we may lose access to some alive objects // if we allocate too little heap right now, we may lose access to some alive objects
// however, after we physically relocate all of our objects we will shrink allocated memory if it is possible // however, after we physically relocate all of our objects we will shrink allocated memory if it is possible
memory_chunk old_heap = heap; memory_chunk old_heap = heap;
heap.begin = mremap( heap.begin = mremap(
heap.begin, heap.begin, WORDS_TO_BYTES(heap.size), WORDS_TO_BYTES(next_heap_pseudo_size), MREMAP_MAYMOVE);
WORDS_TO_BYTES(heap.size),
WORDS_TO_BYTES(next_heap_pseudo_size),
MREMAP_MAYMOVE
);
if (heap.begin == MAP_FAILED) { if (heap.begin == MAP_FAILED) {
perror("ERROR: compact_phase: mremap failed\n"); perror("ERROR: compact_phase: mremap failed\n");
exit(1); exit(1);
@ -114,7 +112,8 @@ void compact_phase(size_t additional_size) {
update_references(&old_heap); update_references(&old_heap);
physically_relocate(&old_heap); physically_relocate(&old_heap);
// shrink it if possible, otherwise this code won'test_small_tree_compaction do anything, in both cases references will remain valid // shrink it if possible, otherwise this code won'test_small_tree_compaction do anything, in both cases references
// will remain valid
heap.begin = mremap( heap.begin = mremap(
heap.begin, heap.begin,
WORDS_TO_BYTES(heap.size), WORDS_TO_BYTES(heap.size),
@ -152,13 +151,13 @@ size_t compute_locations() {
void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end) { void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end) {
for (size_t *ptr = (size_t *)start; ptr < (size_t *)end; ++ptr) { for (size_t *ptr = (size_t *)start; ptr < (size_t *)end; ++ptr) {
size_t ptr_value = *ptr; size_t ptr_value = *ptr;
// this can't be expressed via is_valid_heap_pointer, because this pointer may point area corresponding to the old heap // this can't be expressed via is_valid_heap_pointer, because this pointer may point area corresponding to the old
if (is_valid_pointer((size_t *) ptr_value) // heap
&& (size_t) old_heap->begin <= ptr_value if (is_valid_pointer((size_t *)ptr_value) && (size_t)old_heap->begin <= ptr_value
&& ptr_value <= (size_t) old_heap->current && ptr_value <= (size_t)old_heap->current) {
) {
void *obj_ptr = (void *)heap.begin + ((void *)ptr_value - (void *)old_heap->begin); void *obj_ptr = (void *)heap.begin + ((void *)ptr_value - (void *)old_heap->begin);
void *new_addr = (void*) heap.begin + ((void *) get_forward_address(obj_ptr) - (void *) old_heap->begin); void *new_addr =
(void *)heap.begin + ((void *)get_forward_address(obj_ptr) - (void *)old_heap->begin);
size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr)); size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr));
*(void **)ptr = new_addr + content_offset; *(void **)ptr = new_addr + content_offset;
} }
@ -169,29 +168,28 @@ void update_references(memory_chunk *old_heap) {
heap_iterator it = heap_begin_iterator(); heap_iterator it = heap_begin_iterator();
while (!heap_is_done_iterator(&it)) { while (!heap_is_done_iterator(&it)) {
if (is_marked(get_object_content_ptr(it.current))) { if (is_marked(get_object_content_ptr(it.current))) {
for ( for (obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
!field_is_done_iterator(&field_iter); !field_is_done_iterator(&field_iter);
obj_next_ptr_field_iterator(&field_iter) obj_next_ptr_field_iterator(&field_iter)) {
) {
size_t *field_value = *(size_t **)field_iter.cur_field; size_t *field_value = *(size_t **)field_iter.cur_field;
if (field_value < old_heap->begin || field_value > old_heap->current) { if (field_value < old_heap->begin || field_value > old_heap->current) { continue; }
continue;
}
// this pointer should also be modified according to old_heap->begin // this pointer should also be modified according to old_heap->begin
void *field_obj_content_addr = (void *) heap.begin + (*(void **) field_iter.cur_field - (void *) old_heap->begin); void *field_obj_content_addr =
(void *)heap.begin + (*(void **)field_iter.cur_field - (void *)old_heap->begin);
// important, we calculate new_addr very carefully here, because objects may relocate to another memory chunk // important, we calculate new_addr very carefully here, because objects may relocate to another memory chunk
void *new_addr = void *new_addr =
heap.begin + ((size_t *) get_forward_address(field_obj_content_addr) - (size_t *) old_heap->begin); heap.begin
+ ((size_t *)get_forward_address(field_obj_content_addr) - (size_t *)old_heap->begin);
// update field reference to point to new_addr // update field reference to point to new_addr
// since, we want fields to point to an actual content, we need to add this extra content_offset // since, we want fields to point to an actual content, we need to add this extra content_offset
// because forward_address itself is a pointer to the object's header // because forward_address itself is a pointer to the object's header
size_t content_offset = get_header_size(get_type_row_ptr(field_obj_content_addr)); size_t content_offset = get_header_size(get_type_row_ptr(field_obj_content_addr));
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
if (!is_valid_heap_pointer((void *)(new_addr + content_offset))) { if (!is_valid_heap_pointer((void *)(new_addr + content_offset))) {
fprintf(stderr, "ur: incorrect pointer assignment: on object with id %d", TO_DATA(get_object_content_ptr(it.current))->id); fprintf(stderr,
"ur: incorrect pointer assignment: on object with id %d",
TO_DATA(get_object_content_ptr(it.current))->id);
exit(1); exit(1);
} }
#endif #endif
@ -204,7 +202,8 @@ void update_references(memory_chunk *old_heap) {
scan_and_fix_region(old_heap, (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom); scan_and_fix_region(old_heap, (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom);
// fix pointers from extra_roots // fix pointers from extra_roots
scan_and_fix_region(old_heap, (void*) extra_roots.roots, (size_t*) extra_roots.roots + extra_roots.current_free); scan_and_fix_region(
old_heap, (void *)extra_roots.roots, (size_t *)extra_roots.roots + extra_roots.current_free);
#ifndef DEBUG_VERSION #ifndef DEBUG_VERSION
// fix pointers from static area // fix pointers from static area
@ -234,9 +233,7 @@ bool is_valid_heap_pointer(const size_t *p) {
return !UNBOXED(p) && (size_t)heap.begin <= (size_t)p && (size_t)p <= (size_t)heap.current; return !UNBOXED(p) && (size_t)heap.begin <= (size_t)p && (size_t)p <= (size_t)heap.current;
} }
bool is_valid_pointer(const size_t *p) { bool is_valid_pointer (const size_t *p) { return !UNBOXED(p); }
return !UNBOXED(p);
}
static inline void queue_enqueue (heap_iterator *tail_iter, void *obj) { static inline void queue_enqueue (heap_iterator *tail_iter, void *obj) {
void *tail = tail_iter->current; void *tail = tail_iter->current;
@ -256,13 +253,7 @@ static inline void *queue_dequeue(heap_iterator *head_iter) {
} }
void mark (void *obj) { void mark (void *obj) {
if (!is_valid_heap_pointer(obj)) { if (!is_valid_heap_pointer(obj) || is_marked(obj)) { return; }
return;
}
if (is_marked(obj)) {
return;
}
// TL;DR: [q_head_iter, q_tail_iter) q_head_iter -- current dequeue's victim, q_tail_iter -- place for next enqueue // TL;DR: [q_head_iter, q_tail_iter) q_head_iter -- current dequeue's victim, q_tail_iter -- place for next enqueue
// in forward_address of corresponding element we store address of element to be removed after dequeue operation // in forward_address of corresponding element we store address of element to be removed after dequeue operation
@ -271,19 +262,19 @@ void mark(void *obj) {
heap_iterator q_tail_iter = q_head_iter; heap_iterator q_tail_iter = q_head_iter;
queue_enqueue(&q_tail_iter, obj); queue_enqueue(&q_tail_iter, obj);
// invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked object) // invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked
// also each object is in queue only once // object) also each object is in queue only once
while (q_head_iter.current != q_tail_iter.current) { // means the queue is not empty while (q_head_iter.current != q_tail_iter.current) {
// while the queue is non-empty
void *cur_obj = queue_dequeue(&q_head_iter); void *cur_obj = queue_dequeue(&q_head_iter);
mark_object(cur_obj); mark_object(cur_obj);
void *header_ptr = get_obj_header_ptr(cur_obj, get_type_row_ptr(cur_obj)); void *header_ptr = get_obj_header_ptr(cur_obj, get_type_row_ptr(cur_obj));
for ( for (obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
!field_is_done_iterator(&ptr_field_it); !field_is_done_iterator(&ptr_field_it);
obj_next_ptr_field_iterator(&ptr_field_it) obj_next_ptr_field_iterator(&ptr_field_it)) {
) {
void *field_value = *(void **)ptr_field_it.cur_field; void *field_value = *(void **)ptr_field_it.cur_field;
if (!is_valid_heap_pointer(field_value) || is_marked(field_value) || is_enqueued(field_value)) { if (!is_valid_heap_pointer(field_value) || is_marked(field_value)
|| is_enqueued(field_value)) {
continue; continue;
} }
// if we came to this point it must be true that field_value is unmarked and not currently in queue // if we came to this point it must be true that field_value is unmarked and not currently in queue
@ -309,9 +300,7 @@ void scan_global_area(void) {
} }
#endif #endif
extern void gc_test_and_mark_root(size_t **root) { extern void gc_test_and_mark_root (size_t **root) { mark((void *)*root); }
mark((void *) *root);
}
extern void __init (void) { extern void __init (void) {
signal(SIGSEGV, handler); signal(SIGSEGV, handler);
@ -319,8 +308,8 @@ extern void __init(void) {
srandom(time(NULL)); srandom(time(NULL));
heap.begin = mmap(NULL, space_size, PROT_READ | PROT_WRITE, heap.begin = mmap(
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); NULL, space_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (heap.begin == MAP_FAILED) { if (heap.begin == MAP_FAILED) {
perror("ERROR: __init: mmap failed\n"); perror("ERROR: __init: mmap failed\n");
exit(1); exit(1);
@ -344,9 +333,7 @@ extern void __shutdown(void) {
__gc_stack_bottom = 0; __gc_stack_bottom = 0;
} }
void clear_extra_roots(void) { void clear_extra_roots (void) { extra_roots.current_free = 0; }
extra_roots.current_free = 0;
}
void push_extra_root (void **p) { void push_extra_root (void **p) {
if (extra_roots.current_free >= MAX_EXTRA_ROOTS_NUMBER) { if (extra_roots.current_free >= MAX_EXTRA_ROOTS_NUMBER) {
@ -376,11 +363,9 @@ void pop_extra_root(void **p) {
size_t objects_snapshot (int *object_ids_buf, size_t object_ids_buf_size) { size_t objects_snapshot (int *object_ids_buf, size_t object_ids_buf_size) {
size_t *ids_ptr = (size_t *)object_ids_buf; size_t *ids_ptr = (size_t *)object_ids_buf;
size_t i = 0; size_t i = 0;
for ( for (heap_iterator it = heap_begin_iterator();
heap_iterator it = heap_begin_iterator();
!heap_is_done_iterator(&it) && i < object_ids_buf_size; !heap_is_done_iterator(&it) && i < object_ids_buf_size;
heap_next_obj_iterator(&it), ++i heap_next_obj_iterator(&it), ++i) {
) {
void *header_ptr = it.current; void *header_ptr = it.current;
data *d = TO_DATA(get_object_content_ptr(header_ptr)); data *d = TO_DATA(get_object_content_ptr(header_ptr));
ids_ptr[i] = d->id; ids_ptr[i] = d->id;
@ -392,25 +377,16 @@ extern char* de_hash (int);
void dump_heap () { void dump_heap () {
size_t i = 0; size_t i = 0;
for ( for (heap_iterator it = heap_begin_iterator(); !heap_is_done_iterator(&it);
heap_iterator it = heap_begin_iterator(); heap_next_obj_iterator(&it), ++i) {
!heap_is_done_iterator(&it);
heap_next_obj_iterator(&it), ++i
) {
void *header_ptr = it.current; void *header_ptr = it.current;
void *content_ptr = get_object_content_ptr(header_ptr); void *content_ptr = get_object_content_ptr(header_ptr);
data *d = TO_DATA(content_ptr); data *d = TO_DATA(content_ptr);
lama_type t = get_type_header_ptr(header_ptr); lama_type t = get_type_header_ptr(header_ptr);
switch (t) { switch (t) {
case ARRAY: case ARRAY: fprintf(stderr, "of kind ARRAY\n"); break;
fprintf(stderr, "of kind ARRAY\n"); case CLOSURE: fprintf(stderr, "of kind CLOSURE\n"); break;
break; case STRING: fprintf(stderr, "of kind STRING\n"); break;
case CLOSURE:
fprintf(stderr, "of kind CLOSURE\n");
break;
case STRING:
fprintf(stderr, "of kind STRING\n");
break;
case SEXP: case SEXP:
fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag)); fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag));
break; break;
@ -430,7 +406,6 @@ void set_extra_roots(size_t extra_roots_size, void **extra_roots_ptr) {
#endif #endif
/* Utility functions */ /* Utility functions */
size_t get_forward_address (void *obj) { size_t get_forward_address (void *obj) {
@ -487,9 +462,7 @@ void heap_next_obj_iterator(heap_iterator *it) {
it->current += obj_size; it->current += obj_size;
} }
bool heap_is_done_iterator(heap_iterator *it) { bool heap_is_done_iterator (heap_iterator *it) { return it->current >= heap.current; }
return it->current >= heap.current;
}
lama_type get_type_row_ptr (void *ptr) { lama_type get_type_row_ptr (void *ptr) {
data *data_ptr = TO_DATA(ptr); data *data_ptr = TO_DATA(ptr);
@ -499,21 +472,20 @@ lama_type get_type_row_ptr(void *ptr) {
lama_type get_type_header_ptr (void *ptr) { lama_type get_type_header_ptr (void *ptr) {
int *header = (int *)ptr; int *header = (int *)ptr;
switch (TAG(*header)) { switch (TAG(*header)) {
case ARRAY_TAG: case ARRAY_TAG: return ARRAY;
return ARRAY; case STRING_TAG: return STRING;
case STRING_TAG: case CLOSURE_TAG: return CLOSURE;
return STRING; case SEXP_TAG: return SEXP;
case CLOSURE_TAG:
return CLOSURE;
case SEXP_TAG:
return SEXP;
default: { default: {
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, cur_id=%d", cur_id); fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, cur_id=%d", cur_id);
raise(SIGINT); // only for debug purposes raise(SIGINT); // only for debug purposes
#else #else
fprintf(stderr,
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, ptr is %p, heap size is %d\n", ptr, heap.size); "ERROR: get_type_header_ptr: unknown object header, ptr is %p, "
"heap size is %d\n",
ptr,
heap.size);
#endif #endif
exit(1); exit(1);
} }
@ -528,20 +500,15 @@ size_t obj_size_row_ptr(void *ptr) {
size_t obj_size_header_ptr (void *ptr) { size_t obj_size_header_ptr (void *ptr) {
int len = LEN(*(int *)ptr); int len = LEN(*(int *)ptr);
switch (get_type_header_ptr(ptr)) { switch (get_type_header_ptr(ptr)) {
case ARRAY: case ARRAY: return array_size(len);
return array_size(len); case STRING: return string_size(len);
case STRING: case CLOSURE: return closure_size(len);
return string_size(len); case SEXP: return sexp_size(len);
case CLOSURE:
return closure_size(len);
case SEXP:
return sexp_size(len);
default: { default: {
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
fprintf(stderr, "ERROR: obj_size_header_ptr: unknown object header, cur_id=%d", cur_id); fprintf(stderr, "ERROR: obj_size_header_ptr: unknown object header, cur_id=%d", cur_id);
raise(SIGINT); // only for debug purposes raise(SIGINT); // only for debug purposes
#else #else
perror("ERROR: obj_size_header_ptr: unknown object header"); perror("ERROR: obj_size_header_ptr: unknown object header");
#endif #endif
exit(1); exit(1);
@ -549,54 +516,37 @@ size_t obj_size_header_ptr(void *ptr) {
} }
} }
size_t array_size(size_t sz) { size_t array_size (size_t sz) { return get_header_size(ARRAY) + MEMBER_SIZE * sz; }
return get_header_size(ARRAY) + MEMBER_SIZE * sz;
}
size_t string_size (size_t len) { size_t string_size (size_t len) {
// string should be null terminated // string should be null terminated
return get_header_size(STRING) + len + 1; return get_header_size(STRING) + len + 1;
} }
size_t closure_size(size_t sz) { size_t closure_size (size_t sz) { return get_header_size(CLOSURE) + MEMBER_SIZE * sz; }
return get_header_size(CLOSURE) + MEMBER_SIZE * sz;
}
size_t sexp_size(size_t members) {
return get_header_size(SEXP) + MEMBER_SIZE * members;
}
size_t sexp_size (size_t members) { return get_header_size(SEXP) + MEMBER_SIZE * members; }
obj_field_iterator field_begin_iterator (void *obj) { obj_field_iterator field_begin_iterator (void *obj) {
lama_type type = get_type_header_ptr(obj); lama_type type = get_type_header_ptr(obj);
obj_field_iterator it = {.type = type, .obj_ptr = obj, .cur_field = get_object_content_ptr(obj)}; obj_field_iterator it = {.type = type, .obj_ptr = obj, .cur_field = get_object_content_ptr(obj)};
// since string doesn't have any actual fields we set cur_field to the end of object // since string doesn't have any actual fields we set cur_field to the end of object
if (type == STRING) { if (type == STRING) { it.cur_field = get_end_of_obj(it.obj_ptr); }
it.cur_field = get_end_of_obj(it.obj_ptr);
}
// skip first member which is basically pointer to the code // skip first member which is basically pointer to the code
if (type == CLOSURE) { if (type == CLOSURE) { it.cur_field += MEMBER_SIZE; }
it.cur_field += MEMBER_SIZE;
}
return it; return it;
} }
obj_field_iterator ptr_field_begin_iterator (void *obj) { obj_field_iterator ptr_field_begin_iterator (void *obj) {
obj_field_iterator it = field_begin_iterator(obj); obj_field_iterator it = field_begin_iterator(obj);
// corner case when obj has no fields // corner case when obj has no fields
if (field_is_done_iterator(&it)) { if (field_is_done_iterator(&it)) { return it; }
return it; if (is_valid_pointer(*(size_t **)it.cur_field)) { return it; }
}
if (is_valid_pointer(*(size_t **) it.cur_field)) {
return it;
}
obj_next_ptr_field_iterator(&it); obj_next_ptr_field_iterator(&it);
return it; return it;
} }
void obj_next_field_iterator(obj_field_iterator *it) { void obj_next_field_iterator (obj_field_iterator *it) { it->cur_field += MEMBER_SIZE; }
it->cur_field += MEMBER_SIZE;
}
void obj_next_ptr_field_iterator (obj_field_iterator *it) { void obj_next_ptr_field_iterator (obj_field_iterator *it) {
do { do {
@ -608,29 +558,22 @@ bool field_is_done_iterator(obj_field_iterator *it) {
return it->cur_field >= get_end_of_obj(it->obj_ptr); return it->cur_field >= get_end_of_obj(it->obj_ptr);
} }
void *get_obj_header_ptr(void *ptr, lama_type type) { void *get_obj_header_ptr (void *ptr, lama_type type) { return ptr - get_header_size(type); }
return ptr - get_header_size(type);
}
void *get_object_content_ptr (void *header_ptr) { void *get_object_content_ptr (void *header_ptr) {
lama_type type = get_type_header_ptr(header_ptr); lama_type type = get_type_header_ptr(header_ptr);
return header_ptr + get_header_size(type); return header_ptr + get_header_size(type);
} }
void *get_end_of_obj(void *header_ptr) { void *get_end_of_obj (void *header_ptr) { return header_ptr + obj_size_header_ptr(header_ptr); }
return header_ptr + obj_size_header_ptr(header_ptr);
}
size_t get_header_size (lama_type type) { size_t get_header_size (lama_type type) {
switch (type) { switch (type) {
case STRING: case STRING:
case CLOSURE: case CLOSURE:
case ARRAY: case ARRAY: return DATA_HEADER_SZ;
return DATA_HEADER_SZ; case SEXP: return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
case SEXP: default: perror("ERROR: get_header_size: unknown object type");
return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
default:
perror("ERROR: get_header_size: unknown object type");
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
raise(SIGINT); // only for debug purposes raise(SIGINT); // only for debug purposes
#endif #endif

View file

@ -9,8 +9,11 @@
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2)) #define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2))) #define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
#define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1))) #define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1)))
# define GET_FORWARD_ADDRESS(x) (((size_t) (x)) & (~3)) // since last 2 bits are used for mark-bit and enqueued-bit and due to correct alignment we can expect that last 2 bits don't influence address (they should always be zero) #define GET_FORWARD_ADDRESS(x) \
# define SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((int) (addr)))) // take the last two bits as they are and make all others zero (((size_t)(x)) \
& (~3)) // since last 2 bits are used for mark-bit and enqueued-bit and due to correct alignment we can expect that last 2 bits don't influence address (they should always be zero)
#define SET_FORWARD_ADDRESS(x, addr) \
(x = ((x & 3) | ((int)(addr)))) // take the last two bits as they are and make all others zero
#define EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter #define EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
# define MINIMUM_HEAP_CAPACITY (8) # define MINIMUM_HEAP_CAPACITY (8)
@ -18,9 +21,8 @@
# define MINIMUM_HEAP_CAPACITY (1 << 10) # define MINIMUM_HEAP_CAPACITY (1 << 10)
#endif #endif
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
typedef enum { ARRAY, CLOSURE, STRING, SEXP } lama_type; typedef enum { ARRAY, CLOSURE, STRING, SEXP } lama_type;
@ -45,6 +47,7 @@ typedef struct {
/* GC extra roots */ /* GC extra roots */
#define MAX_EXTRA_ROOTS_NUMBER 32 #define MAX_EXTRA_ROOTS_NUMBER 32
typedef struct { typedef struct {
int current_free; int current_free;
void **roots[MAX_EXTRA_ROOTS_NUMBER]; void **roots[MAX_EXTRA_ROOTS_NUMBER];
@ -62,7 +65,8 @@ void *gc_alloc_on_existing_heap(size_t);
void mark (void *obj); void mark (void *obj);
void mark_phase (void); void mark_phase (void);
// written in ASM, scans stack for pointers to the heap and starts marking process // written in ASM, scans stack for pointers to the heap and starts marking process
extern void __gc_root_scan_stack(void); // TODO: write without ASM, since it is absolutely not necessary extern void
__gc_root_scan_stack (void); // TODO: write without ASM, since it is absolutely not necessary
// marks each pointer from extra roots // marks each pointer from extra roots
void scan_extra_roots (void); void scan_extra_roots (void);
#ifndef DEBUG_VERSION #ifndef DEBUG_VERSION
@ -77,9 +81,12 @@ void update_references(memory_chunk *);
void physically_relocate (memory_chunk *); void physically_relocate (memory_chunk *);
// written in ASM // written in ASM
extern void __gc_init (void); // MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we are working with virtual stack as happens in tests) extern void __gc_init (
extern void __init (void); // should be called before interaction with GC in case of using in tests with virtual stack, otherwise it is automatically invoked by __gc_init void); // MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we are working with virtual stack as happens in tests)
extern void __shutdown (void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC extern void __init (
void); // should be called before interaction with GC in case of using in tests with virtual stack, otherwise it is automatically invoked by __gc_init
extern void __shutdown (
void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC
// written in ASM // written in ASM
extern void __pre_gc (void); extern void __pre_gc (void);
// written in ASM // written in ASM
@ -96,7 +103,6 @@ void push_extra_root (void ** p);
void pop_extra_root (void **p); void pop_extra_root (void **p);
/* Functions for tests */ /* Functions for tests */
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
@ -115,7 +121,6 @@ void set_extra_roots(size_t extra_roots_size, void** extra_roots_ptr);
#endif #endif
/* Utility functions */ /* Utility functions */
// accepts pointer to the start of the region and to the end of the region // accepts pointer to the start of the region and to the end of the region

View file

@ -1,9 +1,4 @@
.data .data
printf_format: .string "Stack root: %lx\n"
printf_format2: .string "BOT: %lx\n"
printf_format3: .string "TOP: %lx\n"
printf_format4: .string "EAX: %lx\n"
printf_format5: .string "LOL\n"
__gc_stack_bottom: .long 0 __gc_stack_bottom: .long 0
__gc_stack_top: .long 0 __gc_stack_top: .long 0
@ -13,8 +8,9 @@ __gc_stack_top: .long 0
.globl __gc_root_scan_stack .globl __gc_root_scan_stack
.globl __gc_stack_top .globl __gc_stack_top
.globl __gc_stack_bottom .globl __gc_stack_bottom
.extern init_pool .extern __init
.extern gc_test_and_copy_root .extern gc_test_and_mark_root
.text .text
__gc_init: __gc_init:

View file

@ -3,8 +3,9 @@
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
#include "runtime.h" #include "runtime.h"
# include "runtime_common.h"
#include "gc.h" #include "gc.h"
#include "runtime_common.h"
#define __ENABLE_GC__ #define __ENABLE_GC__
#ifndef __ENABLE_GC__ #ifndef __ENABLE_GC__
@ -25,6 +26,7 @@ extern void __post_gc ();
# define __post_gc __post_gc_subst # define __post_gc __post_gc_subst
void __pre_gc_subst () { } void __pre_gc_subst () { }
void __post_gc_subst () { } void __post_gc_subst () { }
#endif #endif
@ -53,12 +55,18 @@ void Lassert (void *f, char *s, ...) {
} }
#define ASSERT_BOXED(memo, x) \ #define ASSERT_BOXED(memo, x) \
do if (UNBOXED(x)) failure ("boxed value expected in %s\n", memo); while (0) do \
if (UNBOXED(x)) failure("boxed value expected in %s\n", memo); \
while (0)
#define ASSERT_UNBOXED(memo, x) \ #define ASSERT_UNBOXED(memo, x) \
do if (!UNBOXED(x)) failure ("unboxed value expected in %s\n", memo); while (0) do \
if (!UNBOXED(x)) failure("unboxed value expected in %s\n", memo); \
while (0)
#define ASSERT_STRING(memo, x) \ #define ASSERT_STRING(memo, x) \
do if (!UNBOXED(x) && TAG(TO_DATA(x)->data_header) \ do \
!= STRING_TAG) failure ("string value expected in %s\n", memo); while (0) if (!UNBOXED(x) && TAG(TO_DATA(x)->data_header) != STRING_TAG) \
failure("string value expected in %s\n", memo); \
while (0)
//extern void* alloc (size_t); //extern void* alloc (size_t);
extern void *Bsexp (int n, ...); extern void *Bsexp (int n, ...);
@ -90,8 +98,8 @@ extern int LcompareTags (void *p, void *q) {
#else #else
BOX((GET_SEXP_TAG(TO_SEXP(p)->data_header)) - (GET_SEXP_TAG(TO_SEXP(p)->data_header))); BOX((GET_SEXP_TAG(TO_SEXP(p)->data_header)) - (GET_SEXP_TAG(TO_SEXP(p)->data_header)));
#endif #endif
} } else
else failure ("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header)); failure("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
return 0; // never happens return 0; // never happens
} }
@ -130,9 +138,7 @@ int Ls__Infix_3838 (void *p, void *q) {
} }
// Functional synonym for built-in operator "=="; // Functional synonym for built-in operator "==";
int Ls__Infix_6161 (void *p, void *q) { int Ls__Infix_6161 (void *p, void *q) { return BOX(p == q); }
return BOX(p == q);
}
// Functional synonym for built-in operator "!="; // Functional synonym for built-in operator "!=";
int Ls__Infix_3361 (void *p, void *q) { int Ls__Infix_3361 (void *p, void *q) {
@ -236,7 +242,8 @@ extern int LtagHash (char *s) {
char *q = chars; char *q = chars;
int pos = 0; int pos = 0;
for (; *q && *q != *p; q++, pos++); for (; *q && *q != *p; q++, pos++)
;
if (*q) h = (h << 6) | pos; if (*q) h = (h << 6) | pos;
else failure("tagHash: character not found: %c\n", *p); else failure("tagHash: character not found: %c\n", *p);
@ -244,9 +251,7 @@ extern int LtagHash (char *s) {
p++; p++;
} }
if (strcmp (s, de_hash (h)) != 0) { if (strcmp(s, de_hash(h)) != 0) { failure("%s <-> %s\n", s, de_hash(h)); }
failure ("%s <-> %s\n", s, de_hash(h));
}
return BOX(h); return BOX(h);
} }
@ -258,8 +263,10 @@ char* de_hash (int n) {
p = &buf[5]; p = &buf[5];
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
printf ("de_hash: data_header: %d\n", n); fflush (stdout); print_indent();
printf("de_hash: data_header: %d\n", n);
fflush(stdout);
#endif #endif
*p-- = 0; *p-- = 0;
@ -267,7 +274,8 @@ char* de_hash (int n) {
while (n != 0) { while (n != 0) {
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("char: %c\n", chars [n & 0x003F]); fflush (stdout); printf("char: %c\n", chars[n & 0x003F]);
fflush(stdout);
#endif #endif
*p-- = chars[n & 0x003F]; *p-- = chars[n & 0x003F];
n = n >> 6; n = n >> 6;
@ -297,9 +305,7 @@ static void createStringBuf () {
stringBuf.len = STRINGBUF_INIT; stringBuf.len = STRINGBUF_INIT;
} }
static void deleteStringBuf () { static void deleteStringBuf () { free(stringBuf.contents); }
free (stringBuf.contents);
}
static void extendStringBuf () { static void extendStringBuf () {
int len = stringBuf.len << 1; int len = stringBuf.len << 1;
@ -309,8 +315,7 @@ static void extendStringBuf () {
} }
static void vprintStringBuf (char *fmt, va_list args) { static void vprintStringBuf (char *fmt, va_list args) {
int written = 0, int written = 0, rest = 0;
rest = 0;
char *buf = (char *)BOX(NULL); char *buf = (char *)BOX(NULL);
va_list vsnargs; va_list vsnargs;
@ -353,9 +358,7 @@ static void printValue (void *p) {
a = TO_DATA(p); a = TO_DATA(p);
switch (TAG(a->data_header)) { switch (TAG(a->data_header)) {
case STRING_TAG: case STRING_TAG: printStringBuf("\"%s\"", a->contents); break;
printStringBuf ("\"%s\"", a->contents);
break;
case CLOSURE_TAG: case CLOSURE_TAG:
printStringBuf("<closure "); printStringBuf("<closure ");
@ -387,12 +390,10 @@ static void printValue (void *p) {
if (!UNBOXED(b)) { if (!UNBOXED(b)) {
printStringBuf(", "); printStringBuf(", ");
b = TO_DATA(b); b = TO_DATA(b);
} } else break;
else break;
} }
printStringBuf("}"); printStringBuf("}");
} } else {
else {
printStringBuf("%s", tag); printStringBuf("%s", tag);
if (LEN(a->data_header)) { if (LEN(a->data_header)) {
printStringBuf(" ("); printStringBuf(" (");
@ -403,11 +404,9 @@ static void printValue (void *p) {
printStringBuf(")"); printStringBuf(")");
} }
} }
} } break;
break;
default: default: printStringBuf("*** invalid data_header: 0x%x ***", TAG(a->data_header));
printStringBuf ("*** invalid data_header: 0x%x ***", TAG(a->data_header));
} }
} }
} }
@ -416,14 +415,13 @@ static void stringcat (void *p) {
data *a; data *a;
int i; int i;
if (UNBOXED(p)) ; if (UNBOXED(p))
;
else { else {
a = TO_DATA(p); a = TO_DATA(p);
switch (TAG(a->data_header)) { switch (TAG(a->data_header)) {
case STRING_TAG: case STRING_TAG: printStringBuf("%s", a->contents); break;
printStringBuf ("%s", a->contents);
break;
case SEXP_TAG: { case SEXP_TAG: {
char *tag = de_hash(TO_SEXP(p)->tag); char *tag = de_hash(TO_SEXP(p)->tag);
@ -436,16 +434,12 @@ static void stringcat (void *p) {
b = (data *)((int *)b->contents)[1]; b = (data *)((int *)b->contents)[1];
if (!UNBOXED(b)) { if (!UNBOXED(b)) {
b = TO_DATA(b); b = TO_DATA(b);
} else break;
} }
else break; } else printStringBuf("*** non-list data_header: %s ***", tag);
} } break;
}
else printStringBuf ("*** non-list data_header: %s ***", tag);
}
break;
default: default: printStringBuf("*** invalid data_header: 0x%x ***", TAG(a->data_header));
printStringBuf ("*** invalid data_header: 0x%x ***", TAG(a->data_header));
} }
} }
} }
@ -470,8 +464,7 @@ extern int LmatchSubString (char *subj, char *patt, int pos) {
n = LEN(p->data_header); n = LEN(p->data_header);
if (n + UNBOX(pos) > LEN(s->data_header)) if (n + UNBOX(pos) > LEN(s->data_header)) return BOX(0);
return BOX(0);
return BOX(strncmp(subj + UNBOX(pos), patt, n) == 0); return BOX(strncmp(subj + UNBOX(pos), patt, n) == 0);
} }
@ -501,7 +494,10 @@ extern void* Lsubstring (void *subj, int p, int l) {
} }
failure("substring: index out of bounds (position=%d, length=%d, \ failure("substring: index out of bounds (position=%d, length=%d, \
subject length=%d)", pp, ll, LEN(d->data_header)); subject length=%d)",
pp,
ll,
LEN(d->data_header));
} }
extern struct re_pattern_buffer *Lregexp (char *regexp) { extern struct re_pattern_buffer *Lregexp (char *regexp) {
@ -513,9 +509,7 @@ extern struct re_pattern_buffer *Lregexp (char *regexp) {
int n = (int)re_compile_pattern(regexp, strlen(regexp), b); int n = (int)re_compile_pattern(regexp, strlen(regexp), b);
if (n != 0) { if (n != 0) { failure("%", strerror(n)); };
failure ("%", strerror (n));
};
return b; return b;
} }
@ -531,9 +525,7 @@ extern int LregexpMatch (struct re_pattern_buffer *b, char *s, int pos) {
/* printf ("regexpMatch %x: %s, res=%d\n", b, s+UNBOX(pos), res); */ /* printf ("regexpMatch %x: %s, res=%d\n", b, s+UNBOX(pos), res); */
if (res) { if (res) { return BOX(res); }
return BOX (res);
}
return BOX(res); return BOX(res);
} }
@ -547,8 +539,10 @@ void *Lclone (void *p) {
int n; int n;
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
register int *ebp asm("ebp"); register int *ebp asm("ebp");
indent++; print_indent (); indent++;
printf ("Lclone arg: %p %p\n", &p, p); fflush (stdout); print_indent();
printf("Lclone arg: %p %p\n", &p, p);
fflush(stdout);
#endif #endif
__pre_gc(); __pre_gc();
@ -562,19 +556,22 @@ void *Lclone (void *p) {
case STRING_TAG: case STRING_TAG:
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Lclone: string1 &p=%p p=%p\n", &p, p); fflush (stdout); printf("Lclone: string1 &p=%p p=%p\n", &p, p);
fflush(stdout);
#endif #endif
res = Bstring(TO_DATA(p)->contents); res = Bstring(TO_DATA(p)->contents);
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Lclone: string2 %p %p\n", &p, p); fflush (stdout); printf("Lclone: string2 %p %p\n", &p, p);
fflush(stdout);
#endif #endif
break; break;
case ARRAY_TAG: case ARRAY_TAG:
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Lclone: array &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout); printf("Lclone: array &p=%p p=%p ebp=%p\n", &p, p, ebp);
fflush(stdout);
#endif #endif
obj = (data *)alloc_array(l); obj = (data *)alloc_array(l);
memcpy(obj, TO_DATA(p), array_size(l)); memcpy(obj, TO_DATA(p), array_size(l));
@ -583,7 +580,8 @@ void *Lclone (void *p) {
case CLOSURE_TAG: case CLOSURE_TAG:
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Lclone: closure &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout); printf("Lclone: closure &p=%p p=%p ebp=%p\n", &p, p, ebp);
fflush(stdout);
#endif #endif
obj = (data *)alloc_closure(l); obj = (data *)alloc_closure(l);
memcpy(obj, TO_DATA(p), closure_size(l)); memcpy(obj, TO_DATA(p), closure_size(l));
@ -592,33 +590,38 @@ void *Lclone (void *p) {
case SEXP_TAG: case SEXP_TAG:
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent (); printf ("Lclone: sexp\n"); fflush (stdout); print_indent();
printf("Lclone: sexp\n");
fflush(stdout);
#endif #endif
sobj = (sexp *)alloc_sexp(l); sobj = (sexp *)alloc_sexp(l);
memcpy(sobj, TO_SEXP(p), sexp_size(l)); memcpy(sobj, TO_SEXP(p), sexp_size(l));
res = (void *)sobj->contents.contents; res = (void *)sobj->contents.contents;
break; break;
default: default: failure("invalid data_header %d in clone *****\n", t);
failure ("invalid data_header %d in clone *****\n", t);
} }
pop_extra_root(&p); pop_extra_root(&p);
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent (); printf ("Lclone ends1\n"); fflush (stdout); print_indent();
printf("Lclone ends1\n");
fflush(stdout);
#endif #endif
__post_gc(); __post_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Lclone ends2\n"); fflush (stdout); printf("Lclone ends2\n");
fflush(stdout);
indent--; indent--;
#endif #endif
return res; return res;
} }
#define HASH_DEPTH 3 #define HASH_DEPTH 3
# define HASH_APPEND(acc, x) (((acc + (unsigned) x) << (WORD_SIZE / 2)) | ((acc + (unsigned) x) >> (WORD_SIZE / 2))) #define HASH_APPEND(acc, x) \
(((acc + (unsigned)x) << (WORD_SIZE / 2)) | ((acc + (unsigned)x) >> (WORD_SIZE / 2)))
int inner_hash (int depth, unsigned acc, void *p) { int inner_hash (int depth, unsigned acc, void *p) {
if (depth > HASH_DEPTH) return acc; if (depth > HASH_DEPTH) return acc;
@ -648,9 +651,7 @@ int inner_hash (int depth, unsigned acc, void *p) {
i = 1; i = 1;
break; break;
case ARRAY_TAG: case ARRAY_TAG: i = 0; break;
i = 0;
break;
case SEXP_TAG: { case SEXP_TAG: {
#ifndef DEBUG_PRINT #ifndef DEBUG_PRINT
@ -663,16 +664,13 @@ int inner_hash (int depth, unsigned acc, void *p) {
break; break;
} }
default: default: failure("invalid data_header %d in hash *****\n", t);
failure ("invalid data_header %d in hash *****\n", t);
} }
for (; i<l; i++) for (; i < l; i++) acc = inner_hash(depth + 1, acc, ((void **)a->contents)[i]);
acc = inner_hash (depth+1, acc, ((void**) a->contents)[i]);
return acc; return acc;
} } else return HASH_APPEND(acc, p);
else return HASH_APPEND(acc, p);
} }
extern void *LstringInt (char *b) { extern void *LstringInt (char *b) {
@ -681,34 +679,30 @@ extern void* LstringInt (char *b) {
return (void *)BOX(n); return (void *)BOX(n);
} }
extern int Lhash (void *p) { extern int Lhash (void *p) { return BOX(0x3fffff & inner_hash(0, 0, p)); }
return BOX(0x3fffff & inner_hash (0, 0, p));
}
extern int LflatCompare (void *p, void *q) { extern int LflatCompare (void *p, void *q) {
if (UNBOXED(p)) { if (UNBOXED(p)) {
if (UNBOXED(q)) { if (UNBOXED(q)) { return BOX(UNBOX(p) - UNBOX(q)); }
return BOX (UNBOX(p) - UNBOX(q));
}
return -1; return -1;
} } else if (~UNBOXED(q)) {
else if (~UNBOXED(q)) {
return BOX(p - q); return BOX(p - q);
} } else BOX(1);
else BOX(1);
} }
extern int Lcompare (void *p, void *q) { extern int Lcompare (void *p, void *q) {
# define COMPARE_AND_RETURN(x,y) do if (x != y) return BOX(x - y); while (0) #define COMPARE_AND_RETURN(x, y) \
do \
if (x != y) return BOX(x - y); \
while (0)
if (p == q) return BOX(0); if (p == q) return BOX(0);
if (UNBOXED(p)) { if (UNBOXED(p)) {
if (UNBOXED(q)) return BOX(UNBOX(p) - UNBOX(q)); if (UNBOXED(q)) return BOX(UNBOX(p) - UNBOX(q));
else return BOX(-1); else return BOX(-1);
} } else if (UNBOXED(q)) return BOX(1);
else if (UNBOXED(q)) return BOX(1);
else { else {
if (is_valid_heap_pointer(p)) { if (is_valid_heap_pointer(p)) {
if (is_valid_heap_pointer(q)) { if (is_valid_heap_pointer(q)) {
@ -720,8 +714,7 @@ extern int Lcompare (void *p, void *q) {
COMPARE_AND_RETURN(ta, tb); COMPARE_AND_RETURN(ta, tb);
switch (ta) { switch (ta) {
case STRING_TAG: case STRING_TAG: return BOX(strcmp(a->contents, b->contents));
return BOX(strcmp (a->contents, b->contents));
case CLOSURE_TAG: case CLOSURE_TAG:
COMPARE_AND_RETURN(((void **)a->contents)[0], ((void **)b->contents)[0]); COMPARE_AND_RETURN(((void **)a->contents)[0], ((void **)b->contents)[0]);
@ -738,7 +731,8 @@ extern int Lcompare (void *p, void *q) {
#ifndef DEBUG_PRINT #ifndef DEBUG_PRINT
int ta = TO_SEXP(p)->tag, tb = TO_SEXP(q)->tag; int ta = TO_SEXP(p)->tag, tb = TO_SEXP(q)->tag;
#else #else
int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header), tb = GET_SEXP_TAG(TO_SEXP(q)->data_header); int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header),
tb = GET_SEXP_TAG(TO_SEXP(q)->data_header);
#endif #endif
COMPARE_AND_RETURN(ta, tb); COMPARE_AND_RETURN(ta, tb);
COMPARE_AND_RETURN(la, lb); COMPARE_AND_RETURN(la, lb);
@ -746,8 +740,7 @@ extern int Lcompare (void *p, void *q) {
break; break;
} }
default: default: failure("invalid data_header %d in compare *****\n", ta);
failure ("invalid data_header %d in compare *****\n", ta);
} }
for (; i < la; i++) { for (; i < la; i++) {
@ -756,10 +749,8 @@ extern int Lcompare (void *p, void *q) {
} }
return BOX(0); return BOX(0);
} } else return BOX(-1);
else return BOX(-1); } else if (is_valid_heap_pointer(q)) return BOX(1);
}
else if (is_valid_heap_pointer (q)) return BOX(1);
else return BOX(p - q); else return BOX(p - q);
} }
} }
@ -773,9 +764,7 @@ extern void* Belem (void *p, int i) {
a = TO_DATA(p); a = TO_DATA(p);
i = UNBOX(i); i = UNBOX(i);
if (TAG(a->data_header) == STRING_TAG) { if (TAG(a->data_header) == STRING_TAG) { return (void *)BOX(a->contents[i]); }
return (void*) BOX(a->contents[i]);
}
return (void *)((int *)a->contents)[i]; return (void *)((int *)a->contents)[i];
} }
@ -820,7 +809,8 @@ extern void* Bstring (void *p) {
__pre_gc(); __pre_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
print_indent();
printf("Bstring: call LmakeString %s %p %p %p %i\n", p, &p, p, s, n); printf("Bstring: call LmakeString %s %p %p %p %i\n", p, &p, p, s, n);
fflush(stdout); fflush(stdout);
#endif #endif
@ -829,12 +819,14 @@ extern void* Bstring (void *p) {
pop_extra_root(&p); pop_extra_root(&p);
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("\tBstring: call strncpy: %p %p %p %i\n", &p, p, s, n); fflush(stdout); printf("\tBstring: call strncpy: %p %p %p %i\n", &p, p, s, n);
fflush(stdout);
#endif #endif
strncpy((char *)&TO_DATA(s)->contents, p, n + 1); // +1 because of '\0' in the end of C-strings strncpy((char *)&TO_DATA(s)->contents, p, n + 1); // +1 because of '\0' in the end of C-strings
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("\tBstring: ends\n"); fflush(stdout); printf("\tBstring: ends\n");
fflush(stdout);
indent--; indent--;
#endif #endif
__post_gc(); __post_gc();
@ -892,13 +884,13 @@ extern void* Bclosure (int bn, void *entry, ...) {
__pre_gc(); __pre_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
printf ("Bclosure: create n = %d\n", n); fflush(stdout); print_indent();
printf("Bclosure: create n = %d\n", n);
fflush(stdout);
#endif #endif
argss = (ebp + 12); argss = (ebp + 12);
for (i = 0; i<n; i++, argss++) { for (i = 0; i < n; i++, argss++) { push_extra_root((void **)argss); }
push_extra_root ((void**)argss);
}
r = (data *)alloc_closure(n + 1); r = (data *)alloc_closure(n + 1);
@ -916,13 +908,12 @@ extern void* Bclosure (int bn, void *entry, ...) {
__post_gc(); __post_gc();
argss--; argss--;
for (i = 0; i<n; i++, argss--) { for (i = 0; i < n; i++, argss--) { pop_extra_root((void **)argss); }
pop_extra_root ((void**)argss);
}
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("Bclosure: ends\n", n); fflush(stdout); printf("Bclosure: ends\n", n);
fflush(stdout);
indent--; indent--;
#endif #endif
@ -938,8 +929,10 @@ extern void* Barray (int bn, ...) {
__pre_gc(); __pre_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
printf ("Barray: create n = %d\n", n); fflush(stdout); print_indent();
printf("Barray: create n = %d\n", n);
fflush(stdout);
#endif #endif
r = (data *)alloc_array(n); r = (data *)alloc_array(n);
@ -976,8 +969,10 @@ extern void* Bsexp (int bn, ...) {
__pre_gc(); __pre_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
printf("Bsexp: allocate %zu!\n",sizeof(int) * (n+1)); fflush (stdout); print_indent();
printf("Bsexp: allocate %zu!\n", sizeof(int) * (n + 1));
fflush(stdout);
#endif #endif
int fields_cnt = n - 1; int fields_cnt = n - 1;
r = (sexp *)alloc_sexp(fields_cnt); r = (sexp *)alloc_sexp(fields_cnt);
@ -990,9 +985,7 @@ extern void* Bsexp (int bn, ...) {
ai = va_arg(args, int); ai = va_arg(args, int);
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
if (!UNBOXED(ai)) { if (!UNBOXED(ai)) { assert(is_valid_heap_pointer((size_t *)ai)); }
assert(is_valid_heap_pointer((size_t *) ai));
}
#endif #endif
p = (size_t *)ai; p = (size_t *)ai;
@ -1004,7 +997,8 @@ extern void* Bsexp (int bn, ...) {
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
r->data_header = SEXP_TAG | ((r->data_header) << 3); r->data_header = SEXP_TAG | ((r->data_header) << 3);
print_indent(); print_indent();
printf("Bsexp: ends\n"); fflush (stdout); printf("Bsexp: ends\n");
fflush(stdout);
indent--; indent--;
#endif #endif
@ -1022,10 +1016,12 @@ extern int Btag (void *d, int t, int n) {
else { else {
r = TO_DATA(d); r = TO_DATA(d);
#ifndef DEBUG_PRINT #ifndef DEBUG_PRINT
return BOX(TAG(r->data_header) == SEXP_TAG && TO_SEXP(d)->tag == UNBOX(t) && LEN(r->data_header) == UNBOX(n)); return BOX(TAG(r->data_header) == SEXP_TAG && TO_SEXP(d)->tag == UNBOX(t)
&& LEN(r->data_header) == UNBOX(n));
#else #else
return BOX(TAG(r->data_header) == SEXP_TAG && return BOX(TAG(r->data_header) == SEXP_TAG
GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(test_small_tree_compaction) && LEN(r->data_header) == UNBOX(n)); && GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(test_small_tree_compaction)
&& LEN(r->data_header) == UNBOX(n));
#endif #endif
} }
} }
@ -1035,9 +1031,7 @@ int get_tag(data *d) {
return TAG(d->data_header); return TAG(d->data_header);
} }
int get_len(data *d) { int get_len (data *d) { return LEN(d->data_header); }
return LEN(d->data_header);
}
extern int Barray_patt (void *d, int n) { extern int Barray_patt (void *d, int n) {
data *r; data *r;
@ -1050,14 +1044,14 @@ extern int Barray_patt (void *d, int n) {
} }
extern int Bstring_patt (void *x, void *y) { extern int Bstring_patt (void *x, void *y) {
data *rx = (data *) BOX (NULL), data *rx = (data *)BOX(NULL), *ry = (data *)BOX(NULL);
*ry = (data *) BOX (NULL);
ASSERT_STRING(".string_patt:2", y); ASSERT_STRING(".string_patt:2", y);
if (UNBOXED(x)) return BOX(0); if (UNBOXED(x)) return BOX(0);
else { else {
rx = TO_DATA(x); ry = TO_DATA(y); rx = TO_DATA(x);
ry = TO_DATA(y);
if (TAG(rx->data_header) != STRING_TAG) return BOX(0); if (TAG(rx->data_header) != STRING_TAG) return BOX(0);
@ -1071,14 +1065,9 @@ extern int Bclosure_tag_patt (void *x) {
return BOX(TAG(TO_DATA(x)->data_header) == CLOSURE_TAG); return BOX(TAG(TO_DATA(x)->data_header) == CLOSURE_TAG);
} }
extern int Bboxed_patt (void *x) { extern int Bboxed_patt (void *x) { return BOX(UNBOXED(x) ? 0 : 1); }
return BOX(UNBOXED(x) ? 0 : 1); extern int Bunboxed_patt (void *x) { return BOX(UNBOXED(x) ? 1 : 0); }
}
extern int Bunboxed_patt (void *x) {
return BOX(UNBOXED(x) ? 1 : 0);
}
extern int Barray_tag_patt (void *x) { extern int Barray_tag_patt (void *x) {
if (UNBOXED(x)) return BOX(0); if (UNBOXED(x)) return BOX(0);
@ -1121,9 +1110,7 @@ static void fix_unboxed (char *s, va_list va) {
while (*s) { while (*s) {
if (*s == '%') { if (*s == '%') {
size_t n = p[i]; size_t n = p[i];
if (UNBOXED (n)) { if (UNBOXED(n)) { p[i] = UNBOX(n); }
p[i] = UNBOX(n);
}
i++; i++;
} }
s++; s++;
@ -1142,7 +1129,10 @@ extern void Bmatch_failure (void *v, char *fname, int line, int col) {
createStringBuf(); createStringBuf();
printValue(v); printValue(v);
failure("match failure at %s:%d:%d, value '%s'\n", failure("match failure at %s:%d:%d, value '%s'\n",
fname, UNBOX(line), UNBOX(col), stringBuf.contents); fname,
UNBOX(line),
UNBOX(col),
stringBuf.contents);
} }
extern void * /*Lstrcat*/ Li__Infix_4343 (void *a, void *b) { extern void * /*Lstrcat*/ Li__Infix_4343 (void *a, void *b) {
@ -1207,8 +1197,7 @@ extern void* LgetEnv (char *var) {
char *e = getenv(var); char *e = getenv(var);
void *s; void *s;
if (e == NULL) if (e == NULL) return (void *)BOX(0); // TODO add (void*) cast?
return (void*) BOX(0); // TODO add (void*) cast?
__pre_gc(); __pre_gc();
@ -1219,9 +1208,7 @@ extern void* LgetEnv (char *var) {
return s; return s;
} }
extern int Lsystem (char *cmd) { extern int Lsystem (char *cmd) { return BOX(system(cmd)); }
return BOX (system (cmd));
}
extern void Lfprintf (FILE *f, char *s, ...) { extern void Lfprintf (FILE *f, char *s, ...) {
va_list args = (va_list)BOX(NULL); va_list args = (va_list)BOX(NULL);
@ -1232,9 +1219,7 @@ extern void Lfprintf (FILE *f, char *s, ...) {
va_start(args, s); va_start(args, s);
fix_unboxed(s, args); fix_unboxed(s, args);
if (vfprintf (f, s, args) < 0) { if (vfprintf(f, s, args) < 0) { failure("fprintf (...): %s\n", strerror(errno)); }
failure ("fprintf (...): %s\n", strerror (errno));
}
} }
extern void Lprintf (char *s, ...) { extern void Lprintf (char *s, ...) {
@ -1245,9 +1230,7 @@ extern void Lprintf (char *s, ...) {
va_start(args, s); va_start(args, s);
fix_unboxed(s, args); fix_unboxed(s, args);
if (vprintf (s, args) < 0) { if (vprintf(s, args) < 0) { failure("fprintf (...): %s\n", strerror(errno)); }
failure ("fprintf (...): %s\n", strerror (errno));
}
fflush(stdout); fflush(stdout);
} }
@ -1260,8 +1243,7 @@ extern FILE* Lfopen (char *f, char *m) {
h = fopen(f, m); h = fopen(f, m);
if (h) if (h) return h;
return h;
failure("fopen (\"%s\", \"%s\"): %s, %s, %s\n", f, m, strerror(errno)); failure("fopen (\"%s\", \"%s\"): %s, %s, %s\n", f, m, strerror(errno));
} }
@ -1284,8 +1266,7 @@ extern void* LreadLine () {
return s; return s;
} }
if (errno != 0) if (errno != 0) failure("readLine (): %s\n", strerror(errno));
failure ("readLine (): %s\n", strerror (errno));
return (void *)BOX(0); return (void *)BOX(0);
} }
@ -1323,7 +1304,8 @@ extern void Lfwrite (char *fname, char *contents) {
f = fopen(fname, "w"); f = fopen(fname, "w");
if (f) { if (f) {
if (fprintf (f, "%s", contents) < 0); if (fprintf(f, "%s", contents) < 0)
;
else { else {
fclose(f); fclose(f);
return; return;
@ -1345,21 +1327,13 @@ extern void* Lfexists (char *fname) {
return (void *)BOX(0); // (void*) cast? return (void *)BOX(0); // (void*) cast?
} }
extern void* Lfst (void *v) { extern void *Lfst (void *v) { return Belem(v, BOX(0)); }
return Belem (v, BOX(0));
}
extern void* Lsnd (void *v) { extern void *Lsnd (void *v) { return Belem(v, BOX(1)); }
return Belem (v, BOX(1));
}
extern void* Lhd (void *v) { extern void *Lhd (void *v) { return Belem(v, BOX(0)); }
return Belem (v, BOX(0));
}
extern void* Ltl (void *v) { extern void *Ltl (void *v) { return Belem(v, BOX(1)); }
return Belem (v, BOX(1));
}
/* Lread is an implementation of the "read" construct */ /* Lread is an implementation of the "read" construct */
extern int Lread () { extern int Lread () {
@ -1383,9 +1357,7 @@ extern int Lwrite (int n) {
extern int Lrandom (int n) { extern int Lrandom (int n) {
ASSERT_UNBOXED("Lrandom, 0", n); ASSERT_UNBOXED("Lrandom, 0", n);
if (UNBOX(n) <= 0) { if (UNBOX(n) <= 0) { failure("invalid range in random: %d\n", UNBOX(n)); }
failure ("invalid range in random: %d\n", UNBOX(n));
}
return BOX(random() % UNBOX(n)); return BOX(random() % UNBOX(n));
} }
@ -1406,10 +1378,11 @@ extern void set_args (int argc, char *argv[]) {
__pre_gc(); __pre_gc();
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
indent++; print_indent (); indent++;
printf ("set_args: call: n=%i &p=%p p=%p: ", n, &p, p); fflush(stdout); print_indent();
for (i = 0; i < n; i++) printf("set_args: call: n=%i &p=%p p=%p: ", n, &p, p);
printf("%s ", argv[i]); fflush(stdout);
for (i = 0; i < n; i++) printf("%s ", argv[i]);
printf("EE\n"); printf("EE\n");
#endif #endif
@ -1419,12 +1392,14 @@ extern void set_args (int argc, char *argv[]) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("set_args: iteration %i %p %p ->\n", i, &p, p); fflush(stdout); printf("set_args: iteration %i %p %p ->\n", i, &p, p);
fflush(stdout);
#endif #endif
((int *)p)[i] = (int)Bstring(argv[i]); ((int *)p)[i] = (int)Bstring(argv[i]);
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("set_args: iteration %i <- %p %p\n", i, &p, p); fflush(stdout); printf("set_args: iteration %i <- %p %p\n", i, &p, p);
fflush(stdout);
#endif #endif
} }
@ -1435,7 +1410,8 @@ extern void set_args (int argc, char *argv[]) {
push_extra_root((void **)&global_sysargs); push_extra_root((void **)&global_sysargs);
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
print_indent(); print_indent();
printf ("set_args: end\n", n, &p, p); fflush(stdout); printf("set_args: end\n", n, &p, p);
fflush(stdout);
indent--; indent--;
#endif #endif
} }
@ -1444,10 +1420,6 @@ extern void set_args (int argc, char *argv[]) {
static int enable_GC = 1; static int enable_GC = 1;
extern void LenableGC () { extern void LenableGC () { enable_GC = 1; }
enable_GC = 1;
}
extern void LdisableGC () { extern void LdisableGC () { enable_GC = 0; }
enable_GC = 0;
}

View file

@ -1,18 +1,17 @@
#ifndef __LAMA_RUNTIME__ #ifndef __LAMA_RUNTIME__
#define __LAMA_RUNTIME__ #define __LAMA_RUNTIME__
# include <stdio.h>
# include <stdio.h>
# include <string.h>
# include <stdarg.h>
# include <stdlib.h>
# include <sys/mman.h>
#include <assert.h> #include <assert.h>
# include <errno.h>
# include <regex.h>
# include <time.h>
# include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <regex.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#define WORD_SIZE (CHAR_BIT * sizeof(int)) #define WORD_SIZE (CHAR_BIT * sizeof(int))

View file

@ -19,7 +19,6 @@
#define TAG(x) (x & 0x00000007) #define TAG(x) (x & 0x00000007)
//# define TAG(x) (x & 0x00000006) //# define TAG(x) (x & 0x00000006)
#define SEXP_ONLY_HEADER_SZ (2 * sizeof(int)) #define SEXP_ONLY_HEADER_SZ (2 * sizeof(int))
#ifndef DEBUG_VERSION #ifndef DEBUG_VERSION
@ -44,7 +43,6 @@
#define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))
typedef struct { typedef struct {
// store tag in the last three bits to understand what structure this is, other bits are filled with // store tag in the last three bits to understand what structure this is, other bits are filled with
// other utility info (i.e., size for array, number of fields for s-expression) // other utility info (i.e., size for array, number of fields for s-expression)

View file

@ -1,10 +1,11 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "gc.h" #include "gc.h"
#include "runtime_common.h" #include "runtime_common.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
// function from runtime that maps string to int value // function from runtime that maps string to int value
@ -33,12 +34,11 @@ void test_correct_structure_sizes(void) {
} }
} }
void no_gc_tests(void) { void no_gc_tests (void) { test_correct_structure_sizes(); }
test_correct_structure_sizes();
}
// unfortunately there is no generic function pointer that can hold pointer to function with arbitrary signature // unfortunately there is no generic function pointer that can hold pointer to function with arbitrary signature
extern size_t call_runtime_function(void *virt_stack_pointer, void *function_pointer, size_t num_args, ...); extern size_t call_runtime_function (void *virt_stack_pointer, void *function_pointer,
size_t num_args, ...);
# include "virt_stack.h" # include "virt_stack.h"
@ -54,6 +54,7 @@ void cleanup_test(virt_stack *st) {
vstack_destruct(st); vstack_destruct(st);
__shutdown(); __shutdown();
} }
void force_gc_cycle (virt_stack *st) { void force_gc_cycle (virt_stack *st) {
__gc_stack_top = (size_t)vstack_top(st) - 4; __gc_stack_top = (size_t)vstack_top(st) - 4;
gc_alloc(0); gc_alloc(0);
@ -63,9 +64,7 @@ void force_gc_cycle(virt_stack *st) {
void test_simple_string_alloc (void) { void test_simple_string_alloc (void) {
virt_stack *st = init_test(); virt_stack *st = init_test();
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) { vstack_push(st, BOX(i)); }
vstack_push(st, BOX(i));
}
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "abc")); vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "abc"));
@ -96,7 +95,8 @@ void test_simple_sexp_alloc(void) {
// allocate sexp with one boxed field and push it onto the stack // allocate sexp with one boxed field and push it onto the stack
// calling runtime function Bsexp(BOX(2), BOX(1), LtagHash("test")) // calling runtime function Bsexp(BOX(2), BOX(1), LtagHash("test"))
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bsexp, 3, BOX(2), BOX(1), LtagHash("test"))); vstack_push(
st, call_runtime_function(vstack_top(st) - 4, Bsexp, 3, BOX(2), BOX(1), LtagHash("test")));
const int N = 10; const int N = 10;
int ids[N]; int ids[N];
@ -123,7 +123,9 @@ void test_simple_closure_alloc(void) {
void test_single_object_allocation_with_collection_virtual_stack (void) { void test_single_object_allocation_with_collection_virtual_stack (void) {
virt_stack *st = init_test(); virt_stack *st = init_test();
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); vstack_push(st,
call_runtime_function(
vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
const int N = 10; const int N = 10;
int ids[N]; int ids[N];
@ -151,7 +153,9 @@ void test_garbage_is_reclaimed(void) {
void test_alive_are_not_reclaimed (void) { void test_alive_are_not_reclaimed (void) {
virt_stack *st = init_test(); virt_stack *st = init_test();
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); vstack_push(st,
call_runtime_function(
vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
force_gc_cycle(st); force_gc_cycle(st);
@ -170,7 +174,14 @@ void test_small_tree_compaction(void) {
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "left-s")); vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "left-s"));
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "right-s")); vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "right-s"));
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bsexp, 4, BOX(3), vstack_kth_from_start(st, 0), vstack_kth_from_start(st, 1), LtagHash("tree"))); vstack_push(st,
call_runtime_function(vstack_top(st) - 4,
Bsexp,
4,
BOX(3),
vstack_kth_from_start(st, 0),
vstack_kth_from_start(st, 1),
LtagHash("tree")));
force_gc_cycle(st); force_gc_cycle(st);
const int SZ = 10; const int SZ = 10;
int ids[SZ]; int ids[SZ];
@ -178,9 +189,7 @@ void test_small_tree_compaction(void) {
assert((alive == 3)); assert((alive == 3));
// check that order is indeed preserved // check that order is indeed preserved
for (int i = 0; i < alive - 1; ++i) { for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
assert((ids[i] < ids[i + 1]));
}
cleanup_test(st); cleanup_test(st);
} }
@ -200,22 +209,19 @@ size_t generate_random_obj_forest(virt_stack *st, int cnt, int seed) {
size_t pos[2] = {rand() % vstack_size(st), rand() % vstack_size(st)}; size_t pos[2] = {rand() % vstack_size(st), rand() % vstack_size(st)};
size_t field[2]; size_t field[2];
for (int t = 0; t < 2; ++t) { for (int t = 0; t < 2; ++t) { field[t] = vstack_kth_from_start(st, pos[t]); }
field[t] = vstack_kth_from_start(st, pos[t]);
}
size_t obj; size_t obj;
if (rand() % 2) { if (rand() % 2) {
obj = call_runtime_function(vstack_top(st) - 4, Bsexp, 4, BOX(3), field[0], field[1], LtagHash("test")); obj = call_runtime_function(
vstack_top(st) - 4, Bsexp, 4, BOX(3), field[0], field[1], LtagHash("test"));
} else { } else {
obj = BOX(1); obj = BOX(1);
} }
// whether object is stored on stack // whether object is stored on stack
if (rand() % 2 != 0) { if (rand() % 2 != 0) {
vstack_push(st, obj); vstack_push(st, obj);
if ((obj & 1) == 0) { if ((obj & 1) == 0) { ++alive; }
++alive;
}
} }
++cur_sz; ++cur_sz;
} }
@ -235,9 +241,7 @@ void run_stress_test_random_obj_forest(int seed) {
assert(alive == expectedAlive); assert(alive == expectedAlive);
// check that order is indeed preserved // check that order is indeed preserved
for (int i = 0; i < alive - 1; ++i) { for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
assert((ids[i] < ids[i + 1]));
}
cleanup_test(st); cleanup_test(st);
} }
@ -263,9 +267,7 @@ int main(int argc, char ** argv) {
double diff; double diff;
time(&start); time(&start);
// stress test // stress test
for (int s = 0; s < 100; ++s) { for (int s = 0; s < 100; ++s) { run_stress_test_random_obj_forest(s); }
run_stress_test_random_obj_forest(s);
}
time(&end); time(&end);
diff = difftime(end, start); diff = difftime(end, start);
printf("Stress tests took %.2lf seconds to complete\n", diff); printf("Stress tests took %.2lf seconds to complete\n", diff);

View file

@ -1,13 +1,10 @@
#include "virt_stack.h" #include "virt_stack.h"
#include <malloc.h> #include <malloc.h>
virt_stack *vstack_create() { virt_stack *vstack_create () { return malloc(sizeof(virt_stack)); }
return malloc(sizeof (virt_stack));
}
void vstack_destruct(virt_stack *st) { void vstack_destruct (virt_stack *st) { free(st); }
free(st);
}
void vstack_init (virt_stack *st) { void vstack_init (virt_stack *st) {
st->cur = RUNTIME_VSTACK_SIZE; st->cur = RUNTIME_VSTACK_SIZE;
@ -15,29 +12,21 @@ void vstack_init(virt_stack *st) {
} }
void vstack_push (virt_stack *st, size_t value) { void vstack_push (virt_stack *st, size_t value) {
if (st->cur == 0) { if (st->cur == 0) { assert(0); }
assert(0);
}
--st->cur; --st->cur;
st->buf[st->cur] = value; st->buf[st->cur] = value;
} }
size_t vstack_pop (virt_stack *st) { size_t vstack_pop (virt_stack *st) {
if (st->cur == RUNTIME_VSTACK_SIZE) { if (st->cur == RUNTIME_VSTACK_SIZE) { assert(0); }
assert(0);
}
size_t value = st->buf[st->cur]; size_t value = st->buf[st->cur];
++st->cur; ++st->cur;
return value; return value;
} }
void* vstack_top(virt_stack *st) { void *vstack_top (virt_stack *st) { return st->buf + st->cur; }
return st->buf + st->cur;
}
size_t vstack_size(virt_stack *st) { size_t vstack_size (virt_stack *st) { return RUNTIME_VSTACK_SIZE - st->cur; }
return RUNTIME_VSTACK_SIZE - st->cur;
}
size_t vstack_kth_from_start (virt_stack *st, size_t k) { size_t vstack_kth_from_start (virt_stack *st, size_t k) {
assert(vstack_size(st) > k); assert(vstack_size(st) > k);

View file

@ -6,8 +6,8 @@
#define LAMA_RUNTIME_VIRT_STACK_H #define LAMA_RUNTIME_VIRT_STACK_H
#define RUNTIME_VSTACK_SIZE 100000 #define RUNTIME_VSTACK_SIZE 100000
#include <stddef.h>
#include <assert.h> #include <assert.h>
#include <stddef.h>
struct { struct {
size_t buf[RUNTIME_VSTACK_SIZE + 1]; size_t buf[RUNTIME_VSTACK_SIZE + 1];