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
#include "gc.h"
#include "runtime_common.h"
#include <assert.h>
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/mman.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <execinfo.h>
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();
// all in words
size_t next_heap_size = 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:
size_t next_heap_size =
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
// however, after we physically relocate all of our objects we will shrink allocated memory if it is possible
memory_chunk old_heap = heap;
heap.begin = mremap(
heap.begin,
WORDS_TO_BYTES(heap.size),
WORDS_TO_BYTES(next_heap_pseudo_size),
MREMAP_MAYMOVE
);
heap.begin, WORDS_TO_BYTES(heap.size), WORDS_TO_BYTES(next_heap_pseudo_size), MREMAP_MAYMOVE);
if (heap.begin == MAP_FAILED) {
perror("ERROR: compact_phase: mremap failed\n");
exit(1);
@ -114,7 +112,8 @@ void compact_phase(size_t additional_size) {
update_references(&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,
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) {
for (size_t *ptr = (size_t *)start; ptr < (size_t *)end; ++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
if (is_valid_pointer((size_t *) ptr_value)
&& (size_t) old_heap->begin <= ptr_value
&& ptr_value <= (size_t) old_heap->current
) {
// this can't be expressed via is_valid_heap_pointer, because this pointer may point area corresponding to the old
// heap
if (is_valid_pointer((size_t *)ptr_value) && (size_t)old_heap->begin <= ptr_value
&& ptr_value <= (size_t)old_heap->current) {
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));
*(void **)ptr = new_addr + content_offset;
}
@ -169,29 +168,28 @@ void update_references(memory_chunk *old_heap) {
heap_iterator it = heap_begin_iterator();
while (!heap_is_done_iterator(&it)) {
if (is_marked(get_object_content_ptr(it.current))) {
for (
obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
for (obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
!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;
if (field_value < old_heap->begin || field_value > old_heap->current) {
continue;
}
if (field_value < old_heap->begin || field_value > old_heap->current) { continue; }
// 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
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
// 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
size_t content_offset = get_header_size(get_type_row_ptr(field_obj_content_addr));
#ifdef DEBUG_VERSION
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);
}
#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);
// 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
// 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;
}
bool is_valid_pointer(const size_t *p) {
return !UNBOXED(p);
}
bool is_valid_pointer (const size_t *p) { return !UNBOXED(p); }
static inline void queue_enqueue (heap_iterator *tail_iter, void *obj) {
void *tail = tail_iter->current;
@ -256,13 +253,7 @@ static inline void *queue_dequeue(heap_iterator *head_iter) {
}
void mark (void *obj) {
if (!is_valid_heap_pointer(obj)) {
return;
}
if (is_marked(obj)) {
return;
}
if (!is_valid_heap_pointer(obj) || 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
// 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;
queue_enqueue(&q_tail_iter, obj);
// invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked object)
// also each object is in queue only once
while (q_head_iter.current != q_tail_iter.current) { // means the queue is not empty
// invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked
// object) also each object is in queue only once
while (q_head_iter.current != q_tail_iter.current) {
// while the queue is non-empty
void *cur_obj = queue_dequeue(&q_head_iter);
mark_object(cur_obj);
void *header_ptr = get_obj_header_ptr(cur_obj, get_type_row_ptr(cur_obj));
for (
obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
for (obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
!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;
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;
}
// 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
extern void gc_test_and_mark_root(size_t **root) {
mark((void *) *root);
}
extern void gc_test_and_mark_root (size_t **root) { mark((void *)*root); }
extern void __init (void) {
signal(SIGSEGV, handler);
@ -319,8 +308,8 @@ extern void __init(void) {
srandom(time(NULL));
heap.begin = mmap(NULL, space_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
heap.begin = mmap(
NULL, space_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (heap.begin == MAP_FAILED) {
perror("ERROR: __init: mmap failed\n");
exit(1);
@ -344,9 +333,7 @@ extern void __shutdown(void) {
__gc_stack_bottom = 0;
}
void clear_extra_roots(void) {
extra_roots.current_free = 0;
}
void clear_extra_roots (void) { extra_roots.current_free = 0; }
void push_extra_root (void **p) {
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 *ids_ptr = (size_t *)object_ids_buf;
size_t i = 0;
for (
heap_iterator it = heap_begin_iterator();
for (heap_iterator it = heap_begin_iterator();
!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;
data *d = TO_DATA(get_object_content_ptr(header_ptr));
ids_ptr[i] = d->id;
@ -392,25 +377,16 @@ extern char* de_hash (int);
void dump_heap () {
size_t i = 0;
for (
heap_iterator it = heap_begin_iterator();
!heap_is_done_iterator(&it);
heap_next_obj_iterator(&it), ++i
) {
for (heap_iterator it = heap_begin_iterator(); !heap_is_done_iterator(&it);
heap_next_obj_iterator(&it), ++i) {
void *header_ptr = it.current;
void *content_ptr = get_object_content_ptr(header_ptr);
data *d = TO_DATA(content_ptr);
lama_type t = get_type_header_ptr(header_ptr);
switch (t) {
case ARRAY:
fprintf(stderr, "of kind ARRAY\n");
break;
case CLOSURE:
fprintf(stderr, "of kind CLOSURE\n");
break;
case STRING:
fprintf(stderr, "of kind STRING\n");
break;
case ARRAY: fprintf(stderr, "of kind ARRAY\n"); break;
case CLOSURE: fprintf(stderr, "of kind CLOSURE\n"); break;
case STRING: fprintf(stderr, "of kind STRING\n"); break;
case SEXP:
fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag));
break;
@ -430,7 +406,6 @@ void set_extra_roots(size_t extra_roots_size, void **extra_roots_ptr) {
#endif
/* Utility functions */
size_t get_forward_address (void *obj) {
@ -487,9 +462,7 @@ void heap_next_obj_iterator(heap_iterator *it) {
it->current += obj_size;
}
bool heap_is_done_iterator(heap_iterator *it) {
return it->current >= heap.current;
}
bool heap_is_done_iterator (heap_iterator *it) { return it->current >= heap.current; }
lama_type get_type_row_ptr (void *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) {
int *header = (int *)ptr;
switch (TAG(*header)) {
case ARRAY_TAG:
return ARRAY;
case STRING_TAG:
return STRING;
case CLOSURE_TAG:
return CLOSURE;
case SEXP_TAG:
return SEXP;
case ARRAY_TAG: return ARRAY;
case STRING_TAG: return STRING;
case CLOSURE_TAG: return CLOSURE;
case SEXP_TAG: return SEXP;
default: {
#ifdef DEBUG_VERSION
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, cur_id=%d", cur_id);
raise(SIGINT); // only for debug purposes
#else
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, ptr is %p, heap size is %d\n", ptr, heap.size);
fprintf(stderr,
"ERROR: get_type_header_ptr: unknown object header, ptr is %p, "
"heap size is %d\n",
ptr,
heap.size);
#endif
exit(1);
}
@ -528,20 +500,15 @@ size_t obj_size_row_ptr(void *ptr) {
size_t obj_size_header_ptr (void *ptr) {
int len = LEN(*(int *)ptr);
switch (get_type_header_ptr(ptr)) {
case ARRAY:
return array_size(len);
case STRING:
return string_size(len);
case CLOSURE:
return closure_size(len);
case SEXP:
return sexp_size(len);
case ARRAY: return array_size(len);
case STRING: return string_size(len);
case CLOSURE: return closure_size(len);
case SEXP: return sexp_size(len);
default: {
#ifdef DEBUG_VERSION
fprintf(stderr, "ERROR: obj_size_header_ptr: unknown object header, cur_id=%d", cur_id);
raise(SIGINT); // only for debug purposes
#else
perror("ERROR: obj_size_header_ptr: unknown object header");
#endif
exit(1);
@ -549,54 +516,37 @@ size_t obj_size_header_ptr(void *ptr) {
}
}
size_t array_size(size_t sz) {
return get_header_size(ARRAY) + MEMBER_SIZE * sz;
}
size_t array_size (size_t sz) { return get_header_size(ARRAY) + MEMBER_SIZE * sz; }
size_t string_size (size_t len) {
// string should be null terminated
return get_header_size(STRING) + len + 1;
}
size_t closure_size(size_t 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 closure_size (size_t sz) { return get_header_size(CLOSURE) + MEMBER_SIZE * sz; }
size_t sexp_size (size_t members) { return get_header_size(SEXP) + MEMBER_SIZE * members; }
obj_field_iterator field_begin_iterator (void *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)};
// since string doesn't have any actual fields we set cur_field to the end of object
if (type == STRING) {
it.cur_field = get_end_of_obj(it.obj_ptr);
}
if (type == STRING) { it.cur_field = get_end_of_obj(it.obj_ptr); }
// skip first member which is basically pointer to the code
if (type == CLOSURE) {
it.cur_field += MEMBER_SIZE;
}
if (type == CLOSURE) { it.cur_field += MEMBER_SIZE; }
return it;
}
obj_field_iterator ptr_field_begin_iterator (void *obj) {
obj_field_iterator it = field_begin_iterator(obj);
// corner case when obj has no fields
if (field_is_done_iterator(&it)) {
return it;
}
if (is_valid_pointer(*(size_t **) it.cur_field)) {
return it;
}
if (field_is_done_iterator(&it)) { return it; }
if (is_valid_pointer(*(size_t **)it.cur_field)) { return it; }
obj_next_ptr_field_iterator(&it);
return it;
}
void obj_next_field_iterator(obj_field_iterator *it) {
it->cur_field += MEMBER_SIZE;
}
void obj_next_field_iterator (obj_field_iterator *it) { it->cur_field += MEMBER_SIZE; }
void obj_next_ptr_field_iterator (obj_field_iterator *it) {
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);
}
void *get_obj_header_ptr(void *ptr, lama_type type) {
return ptr - get_header_size(type);
}
void *get_obj_header_ptr (void *ptr, lama_type type) { return ptr - get_header_size(type); }
void *get_object_content_ptr (void *header_ptr) {
lama_type type = get_type_header_ptr(header_ptr);
return header_ptr + get_header_size(type);
}
void *get_end_of_obj(void *header_ptr) {
return header_ptr + obj_size_header_ptr(header_ptr);
}
void *get_end_of_obj (void *header_ptr) { return header_ptr + obj_size_header_ptr(header_ptr); }
size_t get_header_size (lama_type type) {
switch (type) {
case STRING:
case CLOSURE:
case ARRAY:
return DATA_HEADER_SZ;
case SEXP:
return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
default:
perror("ERROR: get_header_size: unknown object type");
case ARRAY: return DATA_HEADER_SZ;
case SEXP: return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
default: perror("ERROR: get_header_size: unknown object type");
#ifdef DEBUG_VERSION
raise(SIGINT); // only for debug purposes
#endif

View file

@ -9,8 +9,11 @@
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
#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 SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((int) (addr)))) // take the last two bits as they are and make all others zero
#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 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
#ifdef DEBUG_VERSION
# define MINIMUM_HEAP_CAPACITY (8)
@ -18,9 +21,8 @@
# define MINIMUM_HEAP_CAPACITY (1 << 10)
#endif
#include <stddef.h>
#include <stdbool.h>
#include <stddef.h>
typedef enum { ARRAY, CLOSURE, STRING, SEXP } lama_type;
@ -45,6 +47,7 @@ typedef struct {
/* GC extra roots */
#define MAX_EXTRA_ROOTS_NUMBER 32
typedef struct {
int current_free;
void **roots[MAX_EXTRA_ROOTS_NUMBER];
@ -62,7 +65,8 @@ void *gc_alloc_on_existing_heap(size_t);
void mark (void *obj);
void mark_phase (void);
// 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
void scan_extra_roots (void);
#ifndef DEBUG_VERSION
@ -77,9 +81,12 @@ void update_references(memory_chunk *);
void physically_relocate (memory_chunk *);
// 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 __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
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 __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
extern void __pre_gc (void);
// written in ASM
@ -96,7 +103,6 @@ void push_extra_root (void ** p);
void pop_extra_root (void **p);
/* Functions for tests */
#ifdef DEBUG_VERSION
@ -115,7 +121,6 @@ void set_extra_roots(size_t extra_roots_size, void** extra_roots_ptr);
#endif
/* Utility functions */
// accepts pointer to the start of the region and to the end of the region

View file

@ -1,9 +1,4 @@
.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_top: .long 0
@ -13,8 +8,9 @@ __gc_stack_top: .long 0
.globl __gc_root_scan_stack
.globl __gc_stack_top
.globl __gc_stack_bottom
.extern init_pool
.extern gc_test_and_copy_root
.extern __init
.extern gc_test_and_mark_root
.text
__gc_init:

View file

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

View file

@ -1,18 +1,17 @@
#ifndef __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 <errno.h>
# include <regex.h>
# include <time.h>
# include <limits.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))

View file

@ -19,7 +19,6 @@
#define TAG(x) (x & 0x00000007)
//# define TAG(x) (x & 0x00000006)
#define SEXP_ONLY_HEADER_SZ (2 * sizeof(int))
#ifndef DEBUG_VERSION
@ -44,7 +43,6 @@
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
typedef struct {
// 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)

View file

@ -1,10 +1,11 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "gc.h"
#include "runtime_common.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG_VERSION
// function from runtime that maps string to int value
@ -33,12 +34,11 @@ void test_correct_structure_sizes(void) {
}
}
void no_gc_tests(void) {
test_correct_structure_sizes();
}
void no_gc_tests (void) { test_correct_structure_sizes(); }
// 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"
@ -54,6 +54,7 @@ void cleanup_test(virt_stack *st) {
vstack_destruct(st);
__shutdown();
}
void force_gc_cycle (virt_stack *st) {
__gc_stack_top = (size_t)vstack_top(st) - 4;
gc_alloc(0);
@ -63,9 +64,7 @@ void force_gc_cycle(virt_stack *st) {
void test_simple_string_alloc (void) {
virt_stack *st = init_test();
for (int i = 0; i < 5; ++i) {
vstack_push(st, BOX(i));
}
for (int i = 0; i < 5; ++i) { vstack_push(st, BOX(i)); }
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
// 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;
int ids[N];
@ -123,7 +123,9 @@ void test_simple_closure_alloc(void) {
void test_single_object_allocation_with_collection_virtual_stack (void) {
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;
int ids[N];
@ -151,7 +153,9 @@ void test_garbage_is_reclaimed(void) {
void test_alive_are_not_reclaimed (void) {
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);
@ -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, "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);
const int SZ = 10;
int ids[SZ];
@ -178,9 +189,7 @@ void test_small_tree_compaction(void) {
assert((alive == 3));
// check that order is indeed preserved
for (int i = 0; i < alive - 1; ++i) {
assert((ids[i] < ids[i + 1]));
}
for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
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 field[2];
for (int t = 0; t < 2; ++t) {
field[t] = vstack_kth_from_start(st, pos[t]);
}
for (int t = 0; t < 2; ++t) { field[t] = vstack_kth_from_start(st, pos[t]); }
size_t obj;
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 {
obj = BOX(1);
}
// whether object is stored on stack
if (rand() % 2 != 0) {
vstack_push(st, obj);
if ((obj & 1) == 0) {
++alive;
}
if ((obj & 1) == 0) { ++alive; }
}
++cur_sz;
}
@ -235,9 +241,7 @@ void run_stress_test_random_obj_forest(int seed) {
assert(alive == expectedAlive);
// check that order is indeed preserved
for (int i = 0; i < alive - 1; ++i) {
assert((ids[i] < ids[i + 1]));
}
for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
cleanup_test(st);
}
@ -263,9 +267,7 @@ int main(int argc, char ** argv) {
double diff;
time(&start);
// stress test
for (int s = 0; s < 100; ++s) {
run_stress_test_random_obj_forest(s);
}
for (int s = 0; s < 100; ++s) { run_stress_test_random_obj_forest(s); }
time(&end);
diff = difftime(end, start);
printf("Stress tests took %.2lf seconds to complete\n", diff);

View file

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

View file

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