From ccd04c2159de2991afdc160c63fa7cb1081d9a1b Mon Sep 17 00:00:00 2001 From: danyaberezun Date: Wed, 31 May 2023 11:01:11 +0200 Subject: [PATCH] add clang-format; reformat files --- runtime/.clang-format | 144 ++++ runtime/gc.c | 953 ++++++++++----------- runtime/gc.h | 177 ++-- runtime/gc_runtime.s | 136 ++- runtime/runtime.c | 1742 +++++++++++++++++++------------------- runtime/runtime.h | 31 +- runtime/runtime_common.h | 70 +- runtime/test_main.c | 390 ++++----- runtime/virt_stack.c | 55 +- runtime/virt_stack.h | 24 +- 10 files changed, 1885 insertions(+), 1837 deletions(-) create mode 100644 runtime/.clang-format diff --git a/runtime/.clang-format b/runtime/.clang-format new file mode 100644 index 000000000..ae47e997f --- /dev/null +++ b/runtime/.clang-format @@ -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 + +--- \ No newline at end of file diff --git a/runtime/gc.c b/runtime/gc.c index e062e4f73..74bf81831 100644 --- a/runtime/gc.c +++ b/runtime/gc.c @@ -1,18 +1,18 @@ -# define _GNU_SOURCE 1 +#define _GNU_SOURCE 1 #include "gc.h" + #include "runtime_common.h" +#include +#include +#include #include #include -#include -#include #include -#include - -#include +#include +#include #include -#include static const size_t INIT_HEAP_SIZE = MINIMUM_HEAP_CAPACITY; @@ -34,647 +34,590 @@ static memory_chunk heap; #endif #ifdef DEBUG_VERSION -void dump_heap(); +void dump_heap (); #endif -void handler(int sig) { - void *array[10]; - size_t size; +void handler (int sig) { + void *array[10]; + size_t size; - // get void*'s for all entries on the stack - size = backtrace(array, 10); + // get void*'s for all entries on the stack + size = backtrace(array, 10); - backtrace_symbols_fd(array, size, STDERR_FILENO); - exit(1); + backtrace_symbols_fd(array, size, STDERR_FILENO); + exit(1); } -void *alloc(size_t size) { +void *alloc (size_t size) { #ifdef DEBUG_VERSION - ++cur_id; + ++cur_id; #endif - size = BYTES_TO_WORDS(size); - void *p = gc_alloc_on_existing_heap(size); - if (!p) { - // not enough place in heap, need to perform GC cycle - return gc_alloc(size); - } + size = BYTES_TO_WORDS(size); + void *p = gc_alloc_on_existing_heap(size); + if (!p) { + // not enough place in heap, need to perform GC cycle + return gc_alloc(size); + } + return p; +} + +void *gc_alloc_on_existing_heap (size_t size) { + if (heap.current + size <= heap.end) { + void *p = (void *)heap.current; + heap.current += size; + memset(p, 0, size * sizeof(size_t)); return p; + } + return NULL; } -void *gc_alloc_on_existing_heap(size_t size) { - if (heap.current + size <= heap.end) { - void *p = (void *) heap.current; - heap.current += size; - memset(p, 0, size * sizeof(size_t)); - return p; - } - return NULL; +void *gc_alloc (size_t size) { + mark_phase(); + + compact_phase(size); + + return gc_alloc_on_existing_heap(size); } -void *gc_alloc(size_t size) { - mark_phase(); - - compact_phase(size); - - return gc_alloc_on_existing_heap(size); -} - -void mark_phase(void) { - __gc_root_scan_stack(); - scan_extra_roots(); +void mark_phase (void) { + __gc_root_scan_stack(); + scan_extra_roots(); #ifndef DEBUG_VERSION - scan_global_area(); + scan_global_area(); #endif } -void compact_phase(size_t additional_size) { - size_t live_size = compute_locations(); +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: - // 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 + // 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: + // 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 - ); - if (heap.begin == MAP_FAILED) { - perror("ERROR: compact_phase: mremap failed\n"); - exit(1); - } - heap.end = heap.begin + next_heap_pseudo_size; - heap.size = next_heap_pseudo_size; - heap.current = heap.begin + (old_heap.current - old_heap.begin); + memory_chunk old_heap = heap; + heap.begin = mremap( + 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); + } + heap.end = heap.begin + next_heap_pseudo_size; + heap.size = next_heap_pseudo_size; + heap.current = heap.begin + (old_heap.current - old_heap.begin); - update_references(&old_heap); - physically_relocate(&old_heap); + 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 - heap.begin = mremap( - heap.begin, - WORDS_TO_BYTES(heap.size), - WORDS_TO_BYTES(next_heap_size), - 0 // in this case we don't set MREMAP_MAYMOVE because it shouldn'test_small_tree_compaction move :) - ); - if (heap.begin == MAP_FAILED) { - perror("ERROR: compact_phase: mremap failed\n"); - exit(1); - } - heap.end = heap.begin + next_heap_size; - heap.size = next_heap_size; - heap.current = heap.begin + live_size; + // 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), + WORDS_TO_BYTES(next_heap_size), + 0 // in this case we don't set MREMAP_MAYMOVE because it shouldn'test_small_tree_compaction move :) + ); + if (heap.begin == MAP_FAILED) { + perror("ERROR: compact_phase: mremap failed\n"); + exit(1); + } + heap.end = heap.begin + next_heap_size; + heap.size = next_heap_size; + heap.current = heap.begin + live_size; } -size_t compute_locations() { - size_t *free_ptr = heap.begin; - heap_iterator scan_iter = heap_begin_iterator(); +size_t compute_locations () { + size_t *free_ptr = heap.begin; + heap_iterator scan_iter = heap_begin_iterator(); - for (; !heap_is_done_iterator(&scan_iter); heap_next_obj_iterator(&scan_iter)) { - void *header_ptr = scan_iter.current; - void *obj_content = get_object_content_ptr(header_ptr); - if (is_marked(obj_content)) { - size_t sz = BYTES_TO_WORDS(obj_size_header_ptr(header_ptr)); - // forward address is responsible for object header pointer - set_forward_address(obj_content, (size_t) free_ptr); - free_ptr += sz; - } + for (; !heap_is_done_iterator(&scan_iter); heap_next_obj_iterator(&scan_iter)) { + void *header_ptr = scan_iter.current; + void *obj_content = get_object_content_ptr(header_ptr); + if (is_marked(obj_content)) { + size_t sz = BYTES_TO_WORDS(obj_size_header_ptr(header_ptr)); + // forward address is responsible for object header pointer + set_forward_address(obj_content, (size_t)free_ptr); + free_ptr += sz; } + } - // it will return number of words - return free_ptr - heap.begin; + // it will return number of words + return free_ptr - heap.begin; } -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 - ) { - 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); - size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr)); - *(void **) ptr = new_addr + content_offset; - } +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) { + 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); + size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr)); + *(void **)ptr = new_addr + content_offset; } + } } -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); - !field_is_done_iterator(&field_iter); - obj_next_ptr_field_iterator(&field_iter) - ) { +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); + !field_is_done_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; - } - // 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); - // 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); - // 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)); + size_t *field_value = *(size_t **)field_iter.cur_field; + 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); + // 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); + // 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); - exit(1); - } -#endif - *(void **) field_iter.cur_field = 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); + exit(1); } - heap_next_obj_iterator(&it); +#endif + *(void **)field_iter.cur_field = new_addr + content_offset; + } } - // fix pointers from stack - scan_and_fix_region(old_heap, (void*) __gc_stack_top + 4, (void*) __gc_stack_bottom); + heap_next_obj_iterator(&it); + } + // fix pointers from stack + 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); + // fix pointers from extra_roots + 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 - scan_and_fix_region(old_heap, (void*) &__start_custom_data, (void*) &__stop_custom_data); + // fix pointers from static area + scan_and_fix_region(old_heap, (void *)&__start_custom_data, (void *)&__stop_custom_data); #endif } -void physically_relocate(memory_chunk *old_heap) { - heap_iterator from_iter = heap_begin_iterator(); - - while (!heap_is_done_iterator(&from_iter)) { - void *obj = get_object_content_ptr(from_iter.current); - heap_iterator next_iter = from_iter; - heap_next_obj_iterator(&next_iter); - if (is_marked(obj)) { - // Move the object from its old location to its new location relative to - // the heap's (possibly new) location, 'to' points to future object header - size_t *to = heap.begin + ((size_t *) get_forward_address(obj) - (size_t *) old_heap->begin); - memmove(to, from_iter.current, obj_size_header_ptr(from_iter.current)); - unmark_object(get_object_content_ptr(to)); - } - from_iter = next_iter; - } -} - -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); -} - -static inline void queue_enqueue(heap_iterator *tail_iter, void *obj) { - void *tail = tail_iter->current; - void *tail_content = get_object_content_ptr(tail); - set_forward_address(tail_content, (size_t) obj); - make_enqueued(obj); - heap_next_obj_iterator(tail_iter); -} - -static inline void *queue_dequeue(heap_iterator *head_iter) { - void *head = head_iter->current; - void *head_content = get_object_content_ptr(head); - void *value = (void*) get_forward_address(head_content); - make_dequeued(value); - heap_next_obj_iterator(head_iter); - return value; -} - -void mark(void *obj) { - if (!is_valid_heap_pointer(obj)) { - return; - } +void physically_relocate (memory_chunk *old_heap) { + heap_iterator from_iter = heap_begin_iterator(); + while (!heap_is_done_iterator(&from_iter)) { + void *obj = get_object_content_ptr(from_iter.current); + heap_iterator next_iter = from_iter; + heap_next_obj_iterator(&next_iter); 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 - // in forward_address of corresponding element we store address of element to be removed after dequeue operation - heap_iterator q_head_iter = heap_begin_iterator(); - // iterator where we will write address of the element that is going to be enqueued - 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 - 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); - !field_is_done_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)) { - continue; - } - // if we came to this point it must be true that field_value is unmarked and not currently in queue - // thus, we maintain the invariant - queue_enqueue(&q_tail_iter, field_value); - } + // Move the object from its old location to its new location relative to + // the heap's (possibly new) location, 'to' points to future object header + size_t *to = heap.begin + ((size_t *)get_forward_address(obj) - (size_t *)old_heap->begin); + memmove(to, from_iter.current, obj_size_header_ptr(from_iter.current)); + unmark_object(get_object_content_ptr(to)); } + from_iter = next_iter; + } } -void scan_extra_roots(void) { - for (int i = 0; i < extra_roots.current_free; ++i) { - // this dereferencing is safe since runtime is pushing correct pointers into extra_roots - mark(*extra_roots.roots[i]); +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); } + +static inline void queue_enqueue (heap_iterator *tail_iter, void *obj) { + void *tail = tail_iter->current; + void *tail_content = get_object_content_ptr(tail); + set_forward_address(tail_content, (size_t)obj); + make_enqueued(obj); + heap_next_obj_iterator(tail_iter); +} + +static inline void *queue_dequeue (heap_iterator *head_iter) { + void *head = head_iter->current; + void *head_content = get_object_content_ptr(head); + void *value = (void *)get_forward_address(head_content); + make_dequeued(value); + heap_next_obj_iterator(head_iter); + return value; +} + +void mark (void *obj) { + 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 + heap_iterator q_head_iter = heap_begin_iterator(); + // iterator where we will write address of the element that is going to be enqueued + 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) { + // 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); + !field_is_done_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)) { + continue; + } + // if we came to this point it must be true that field_value is unmarked and not currently in queue + // thus, we maintain the invariant + queue_enqueue(&q_tail_iter, field_value); } + } +} + +void scan_extra_roots (void) { + for (int i = 0; i < extra_roots.current_free; ++i) { + // this dereferencing is safe since runtime is pushing correct pointers into extra_roots + mark(*extra_roots.roots[i]); + } } #ifndef DEBUG_VERSION -void scan_global_area(void) { - // __start_custom_data is pointing to beginning of global area, thus all dereferencings are safe - for (size_t *ptr = (size_t *) &__start_custom_data; ptr < (size_t *) &__stop_custom_data; ++ptr) { - mark(*(void **)ptr); - } +void scan_global_area (void) { + // __start_custom_data is pointing to beginning of global area, thus all dereferencings are safe + for (size_t *ptr = (size_t *)&__start_custom_data; ptr < (size_t *)&__stop_custom_data; ++ptr) { + mark(*(void **)ptr); + } } #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); + size_t space_size = INIT_HEAP_SIZE * sizeof(size_t); + + srandom(time(NULL)); + + 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); + } + heap.end = heap.begin + INIT_HEAP_SIZE; + heap.size = INIT_HEAP_SIZE; + heap.current = heap.begin; + clear_extra_roots(); } -extern void __init(void) { - signal(SIGSEGV, handler); - size_t space_size = INIT_HEAP_SIZE * sizeof(size_t); - - srandom(time(NULL)); - - 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); - } - heap.end = heap.begin + INIT_HEAP_SIZE; - heap.size = INIT_HEAP_SIZE; - heap.current = heap.begin; - clear_extra_roots(); -} - -extern void __shutdown(void) { - munmap(heap.begin, heap.size); +extern void __shutdown (void) { + munmap(heap.begin, heap.size); #ifdef DEBUG_VERSION - cur_id = 0; + cur_id = 0; #endif - heap.begin = NULL; - heap.end = NULL; - heap.size = 0; - heap.current = NULL; - __gc_stack_top = 0; - __gc_stack_bottom = 0; + heap.begin = NULL; + heap.end = NULL; + heap.size = 0; + heap.current = NULL; + __gc_stack_top = 0; + __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) { + perror("ERROR: push_extra_roots: extra_roots_pool overflow"); + exit(1); + } + extra_roots.roots[extra_roots.current_free] = p; + extra_roots.current_free++; } -void push_extra_root(void **p) { - if (extra_roots.current_free >= MAX_EXTRA_ROOTS_NUMBER) { - perror("ERROR: push_extra_roots: extra_roots_pool overflow"); - exit(1); - } - extra_roots.roots[extra_roots.current_free] = p; - extra_roots.current_free++; -} - -void pop_extra_root(void **p) { - if (extra_roots.current_free == 0) { - perror("ERROR: pop_extra_root: extra_roots are empty"); - exit(1); - } - extra_roots.current_free--; - if (extra_roots.roots[extra_roots.current_free] != p) { - perror("ERROR: pop_extra_root: stack invariant violation"); - exit(1); - } +void pop_extra_root (void **p) { + if (extra_roots.current_free == 0) { + perror("ERROR: pop_extra_root: extra_roots are empty"); + exit(1); + } + extra_roots.current_free--; + if (extra_roots.roots[extra_roots.current_free] != p) { + perror("ERROR: pop_extra_root: stack invariant violation"); + exit(1); + } } /* Functions for tests */ #ifdef DEBUG_VERSION -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(); - !heap_is_done_iterator(&it) && i < object_ids_buf_size; - 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; +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(); + !heap_is_done_iterator(&it) && i < object_ids_buf_size; + 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; + } + return i; +} + +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) { + 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 SEXP: + fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag)); + break; } - return i; + } } -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 - ) { - 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 SEXP: - fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag)); - break; - } - } +void set_stack (size_t stack_top, size_t stack_bottom) { + __gc_stack_top = stack_top; + __gc_stack_bottom = stack_bottom; } -void set_stack(size_t stack_top, size_t stack_bottom) { - __gc_stack_top = stack_top; - __gc_stack_bottom = stack_bottom; -} - -void set_extra_roots(size_t extra_roots_size, void **extra_roots_ptr) { - memcpy(extra_roots.roots, extra_roots_ptr, MIN(sizeof(extra_roots.roots), extra_roots_size)); - clear_extra_roots(); +void set_extra_roots (size_t extra_roots_size, void **extra_roots_ptr) { + memcpy(extra_roots.roots, extra_roots_ptr, MIN(sizeof(extra_roots.roots), extra_roots_size)); + clear_extra_roots(); } #endif - /* Utility functions */ -size_t get_forward_address(void *obj) { - data *d = TO_DATA(obj); - return GET_FORWARD_ADDRESS(d->forward_address); +size_t get_forward_address (void *obj) { + data *d = TO_DATA(obj); + return GET_FORWARD_ADDRESS(d->forward_address); } -void set_forward_address(void *obj, size_t addr) { - data *d = TO_DATA(obj); - SET_FORWARD_ADDRESS(d->forward_address, addr); +void set_forward_address (void *obj, size_t addr) { + data *d = TO_DATA(obj); + SET_FORWARD_ADDRESS(d->forward_address, addr); } -bool is_marked(void *obj) { - data *d = TO_DATA(obj); - int mark_bit = GET_MARK_BIT(d->forward_address); - return mark_bit; +bool is_marked (void *obj) { + data *d = TO_DATA(obj); + int mark_bit = GET_MARK_BIT(d->forward_address); + return mark_bit; } -void mark_object(void *obj) { - data *d = TO_DATA(obj); - SET_MARK_BIT(d->forward_address); +void mark_object (void *obj) { + data *d = TO_DATA(obj); + SET_MARK_BIT(d->forward_address); } -void unmark_object(void *obj) { - data *d = TO_DATA(obj); - RESET_MARK_BIT(d->forward_address); +void unmark_object (void *obj) { + data *d = TO_DATA(obj); + RESET_MARK_BIT(d->forward_address); } -bool is_enqueued(void *obj) { - data *d = TO_DATA(obj); - return IS_ENQUEUED(d->forward_address) != 0; +bool is_enqueued (void *obj) { + data *d = TO_DATA(obj); + return IS_ENQUEUED(d->forward_address) != 0; } -void make_enqueued(void *obj) { - data *d = TO_DATA(obj); - MAKE_ENQUEUED(d->forward_address); +void make_enqueued (void *obj) { + data *d = TO_DATA(obj); + MAKE_ENQUEUED(d->forward_address); } -void make_dequeued(void *obj) { - data *d = TO_DATA(obj); - MAKE_DEQUEUED(d->forward_address); +void make_dequeued (void *obj) { + data *d = TO_DATA(obj); + MAKE_DEQUEUED(d->forward_address); } -heap_iterator heap_begin_iterator() { - heap_iterator it = {.current=heap.begin}; - return it; +heap_iterator heap_begin_iterator () { + heap_iterator it = {.current = heap.begin}; + return it; } -void heap_next_obj_iterator(heap_iterator *it) { - void *ptr = it->current; - size_t obj_size = obj_size_header_ptr(ptr); - // make sure we take alignment into consideration - obj_size = BYTES_TO_WORDS(obj_size); - it->current += obj_size; +void heap_next_obj_iterator (heap_iterator *it) { + void *ptr = it->current; + size_t obj_size = obj_size_header_ptr(ptr); + // make sure we take alignment into consideration + obj_size = BYTES_TO_WORDS(obj_size); + 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); + return get_type_header_ptr(data_ptr); } -lama_type get_type_row_ptr(void *ptr) { - data *data_ptr = TO_DATA(ptr); - return get_type_header_ptr(data_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; - default: { +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; + 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 + 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); - } + exit(1); } + } } -size_t obj_size_row_ptr(void *ptr) { - data *data_ptr = TO_DATA(ptr); - return obj_size_header_ptr(data_ptr); +size_t obj_size_row_ptr (void *ptr) { + data *data_ptr = TO_DATA(ptr); + return obj_size_header_ptr(data_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); - default: { +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); + 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 + 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"); + perror("ERROR: obj_size_header_ptr: unknown object header"); #endif - exit(1); - } + exit(1); } + } } -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 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; } + +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); } + // skip first member which is basically pointer to the code + if (type == CLOSURE) { it.cur_field += MEMBER_SIZE; } + return it; } -size_t closure_size(size_t sz) { - return get_header_size(CLOSURE) + MEMBER_SIZE * sz; +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; } + obj_next_ptr_field_iterator(&it); + return it; } -size_t sexp_size(size_t members) { - return get_header_size(SEXP) + MEMBER_SIZE * members; +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 { + obj_next_field_iterator(it); + } while (!field_is_done_iterator(it) && !is_valid_pointer(*(size_t **)it->cur_field)); } - -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); - } - // skip first member which is basically pointer to the code - if (type == CLOSURE) { - it.cur_field += MEMBER_SIZE; - } - return it; +bool field_is_done_iterator (obj_field_iterator *it) { + return it->cur_field >= get_end_of_obj(it->obj_ptr); } -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; - } - obj_next_ptr_field_iterator(&it); - return it; +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 obj_next_field_iterator(obj_field_iterator *it) { - it->cur_field += MEMBER_SIZE; -} +void *get_end_of_obj (void *header_ptr) { return header_ptr + obj_size_header_ptr(header_ptr); } -void obj_next_ptr_field_iterator(obj_field_iterator *it) { - do { - obj_next_field_iterator(it); - } while (!field_is_done_iterator(it) && !is_valid_pointer(*(size_t **) it->cur_field)); -} - -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_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); -} - -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"); +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"); #ifdef DEBUG_VERSION - raise(SIGINT); // only for debug purposes + raise(SIGINT); // only for debug purposes #endif - exit(1); - } + exit(1); + } } -void *alloc_string(int len) { - data *obj = alloc(string_size(len)); - obj->data_header = STRING_TAG | (len << 3); +void *alloc_string (int len) { + data *obj = alloc(string_size(len)); + obj->data_header = STRING_TAG | (len << 3); #ifdef DEBUG_VERSION - obj->id = cur_id; + obj->id = cur_id; #endif - obj->forward_address = 0; - return obj; + obj->forward_address = 0; + return obj; } -void *alloc_array(int len) { - data *obj = alloc(array_size(len)); - obj->data_header = ARRAY_TAG | (len << 3); +void *alloc_array (int len) { + data *obj = alloc(array_size(len)); + obj->data_header = ARRAY_TAG | (len << 3); #ifdef DEBUG_VERSION - obj->id = cur_id; + obj->id = cur_id; #endif - obj->forward_address = 0; - return obj; + obj->forward_address = 0; + return obj; } -void *alloc_sexp(int members) { - sexp *obj = alloc(sexp_size(members)); - obj->sexp_header = obj->contents.data_header = SEXP_TAG | (members << 3); +void *alloc_sexp (int members) { + sexp *obj = alloc(sexp_size(members)); + obj->sexp_header = obj->contents.data_header = SEXP_TAG | (members << 3); #ifdef DEBUG_VERSION - obj->contents.id = cur_id; + obj->contents.id = cur_id; #endif - obj->contents.forward_address = 0; - obj->tag = 0; - return obj; + obj->contents.forward_address = 0; + obj->tag = 0; + return obj; } -void *alloc_closure(int captured) { - data *obj = alloc(closure_size(captured)); - obj->data_header = CLOSURE_TAG | (captured << 3); +void *alloc_closure (int captured) { + data *obj = alloc(closure_size(captured)); + obj->data_header = CLOSURE_TAG | (captured << 3); #ifdef DEBUG_VERSION - obj->id = cur_id; + obj->id = cur_id; #endif - obj->forward_address = 0; - return obj; + obj->forward_address = 0; + return obj; } diff --git a/runtime/gc.h b/runtime/gc.h index 957f239e4..882825401 100644 --- a/runtime/gc.h +++ b/runtime/gc.h @@ -3,99 +3,105 @@ #include "runtime_common.h" -# define GET_MARK_BIT(x) (((int) (x)) & 1) -# define SET_MARK_BIT(x) (x = (((int) (x)) | 1)) -# define IS_ENQUEUED(x) (((int) (x)) & 2) -# 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 EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter +#define GET_MARK_BIT(x) (((int)(x)) & 1) +#define SET_MARK_BIT(x) (x = (((int)(x)) | 1)) +#define IS_ENQUEUED(x) (((int)(x)) & 2) +#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 EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter #ifdef DEBUG_VERSION -# define MINIMUM_HEAP_CAPACITY (8) +# define MINIMUM_HEAP_CAPACITY (8) #else -# define MINIMUM_HEAP_CAPACITY (1<<10) +# define MINIMUM_HEAP_CAPACITY (1 << 10) #endif - -#include #include +#include typedef enum { ARRAY, CLOSURE, STRING, SEXP } lama_type; typedef struct { - size_t *current; + size_t *current; } heap_iterator; typedef struct { - // holds type of object, which fields we are iterating over - lama_type type; - // here a pointer to the object header is stored - void *obj_ptr; - void *cur_field; + // holds type of object, which fields we are iterating over + lama_type type; + // here a pointer to the object header is stored + void *obj_ptr; + void *cur_field; } obj_field_iterator; typedef struct { - size_t * begin; - size_t * end; - size_t * current; - size_t size; + size_t *begin; + size_t *end; + size_t *current; + size_t size; } memory_chunk; /* GC extra roots */ -# define MAX_EXTRA_ROOTS_NUMBER 32 +#define MAX_EXTRA_ROOTS_NUMBER 32 + typedef struct { - int current_free; - void ** roots[MAX_EXTRA_ROOTS_NUMBER]; + int current_free; + void **roots[MAX_EXTRA_ROOTS_NUMBER]; } extra_roots_pool; // the only GC-related function that should be exposed, others are useful for tests and internal implementation // allocates object of the given size on the heap -void* alloc(size_t); +void *alloc(size_t); // takes number of words as a parameter -void* gc_alloc(size_t); +void *gc_alloc(size_t); // takes number of words as a parameter void *gc_alloc_on_existing_heap(size_t); // specific for mark-and-compact_phase gc -void mark(void *obj); -void mark_phase(void); +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); +void scan_extra_roots (void); #ifndef DEBUG_VERSION // marks each valid pointer from global area -void scan_global_area(void); +void scan_global_area (void); #endif // takes number of words that are required to be allocated somewhere on the heap -void compact_phase(size_t additional_size); +void compact_phase (size_t additional_size); // specific for Lisp-2 algorithm -size_t compute_locations(); -void update_references(memory_chunk *); -void physically_relocate(memory_chunk *); +size_t compute_locations (); +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); +extern void __pre_gc (void); // written in ASM -extern void __post_gc (void); +extern void __post_gc (void); // invoked from ASM -extern void gc_test_and_mark_root(size_t ** root); -inline bool is_valid_heap_pointer(const size_t *); -inline bool is_valid_pointer(const size_t *); +extern void gc_test_and_mark_root (size_t **root); +inline bool is_valid_heap_pointer (const size_t *); +inline bool is_valid_pointer (const size_t *); void clear_extra_roots (void); -void push_extra_root (void ** p); - -void pop_extra_root (void ** p); +void push_extra_root (void **p); +void pop_extra_root (void **p); /* Functions for tests */ @@ -105,96 +111,95 @@ void pop_extra_root (void ** p); // returns number of ids dumped // object_ids_buf is pointer to area preallocated by user for dumping ids of objects in heap // object_ids_buf_size is in WORDS, NOT BYTES -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); // essential function to mock program stack -void set_stack(size_t stack_top, size_t stack_bottom); +void set_stack (size_t stack_top, size_t stack_bottom); // function to mock extra roots (Lama specific) -void set_extra_roots(size_t extra_roots_size, void** extra_roots_ptr); +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 // scans it and if it meets a pointer, it should be modified in according to forward address -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); // takes a pointer to an object content as an argument, returns forwarding address -size_t get_forward_address(void *obj); +size_t get_forward_address (void *obj); // takes a pointer to an object content as an argument, sets forwarding address to value 'addr' -void set_forward_address(void *obj, size_t addr); +void set_forward_address (void *obj, size_t addr); // takes a pointer to an object content as an argument, returns whether this object was marked as live -bool is_marked(void *obj); +bool is_marked (void *obj); // takes a pointer to an object content as an argument, marks the object as live -void mark_object(void *obj); +void mark_object (void *obj); // takes a pointer to an object content as an argument, marks the object as dead -void unmark_object(void *obj); +void unmark_object (void *obj); // takes a pointer to an object content as an argument, returns whether this object was enqueued to the queue (which is used in mark phase) -bool is_enqueued(void *obj); +bool is_enqueued (void *obj); // takes a pointer to an object content as an argument, marks object as enqueued -void make_enqueued(void *obj); +void make_enqueued (void *obj); // takes a pointer to an object content as an argument, unmarks object as enqueued -void make_dequeued(void *obj); +void make_dequeued (void *obj); // returns iterator to an object with the lowest address -heap_iterator heap_begin_iterator(); -void heap_next_obj_iterator(heap_iterator *it); -bool heap_is_done_iterator(heap_iterator *it); +heap_iterator heap_begin_iterator (); +void heap_next_obj_iterator (heap_iterator *it); +bool heap_is_done_iterator (heap_iterator *it); // returns correct type when pointer to actual data is passed (header is excluded) -lama_type get_type_row_ptr(void *ptr); +lama_type get_type_row_ptr (void *ptr); // returns correct type when pointer to an object header is passed -lama_type get_type_header_ptr(void *ptr); +lama_type get_type_header_ptr (void *ptr); // returns correct object size (together with header) of an object, ptr is pointer to an actual data is passed (header is excluded) -size_t obj_size_row_ptr(void *ptr); +size_t obj_size_row_ptr (void *ptr); // returns correct object size (together with header) of an object, ptr is pointer to an object header -size_t obj_size_header_ptr(void *ptr); +size_t obj_size_header_ptr (void *ptr); // returns total padding size that we need to store given object type -size_t get_header_size(lama_type type); +size_t get_header_size (lama_type type); // returns number of bytes that are required to allocate array with 'sz' elements (header included) -size_t array_size(size_t sz); +size_t array_size (size_t sz); // returns number of bytes that are required to allocate string of length 'l' (header included) -size_t string_size(size_t len); +size_t string_size (size_t len); // TODO: ask if it is actually so? number of captured elements is actually sz-1 and 1 extra word is code ptr? // returns number of bytes that are required to allocate closure with 'sz-1' captured values (header included) -size_t closure_size(size_t sz); +size_t closure_size (size_t sz); // returns number of bytes that are required to allocate s-expression with 'members' fields (header included) -size_t sexp_size(size_t members); +size_t sexp_size (size_t members); // returns an iterator over object fields, obj is ptr to object header // (in case of s-exp, it is mandatory that obj ptr is very beginning of the object, // considering that now we store two versions of header in there) -obj_field_iterator field_begin_iterator(void *obj); +obj_field_iterator field_begin_iterator (void *obj); // returns an iterator over object fields which are actual pointers, obj is ptr to object header // (in case of s-exp, it is mandatory that obj ptr is very beginning of the object, // considering that now we store two versions of header in there) -obj_field_iterator ptr_field_begin_iterator(void *obj); +obj_field_iterator ptr_field_begin_iterator (void *obj); // moves the iterator to next object field -void obj_next_field_iterator(obj_field_iterator *it); +void obj_next_field_iterator (obj_field_iterator *it); // moves the iterator to the next object field which is an actual pointer -void obj_next_ptr_field_iterator(obj_field_iterator *it); +void obj_next_ptr_field_iterator (obj_field_iterator *it); // returns if we are done iterating over fields of the object -bool field_is_done_iterator(obj_field_iterator *it); +bool field_is_done_iterator (obj_field_iterator *it); // ptr is pointer to the actual object content, returns pointer to the very beginning of the object (header) -void* get_obj_header_ptr(void *ptr, lama_type type); -void* get_object_content_ptr(void *header_ptr); -void* get_end_of_obj(void *header_ptr); +void *get_obj_header_ptr (void *ptr, lama_type type); +void *get_object_content_ptr (void *header_ptr); +void *get_end_of_obj (void *header_ptr); -void *alloc_string(int len); -void *alloc_array(int len); -void *alloc_sexp(int members); -void *alloc_closure(int captured); +void *alloc_string (int len); +void *alloc_array (int len); +void *alloc_sexp (int members); +void *alloc_closure (int captured); -#endif \ No newline at end of file +#endif diff --git a/runtime/gc_runtime.s b/runtime/gc_runtime.s index 27168e452..2186b013d 100644 --- a/runtime/gc_runtime.s +++ b/runtime/gc_runtime.s @@ -1,67 +1,63 @@ - .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" + .data __gc_stack_bottom: .long 0 -__gc_stack_top: .long 0 +__gc_stack_top: .long 0 - .globl __pre_gc - .globl __post_gc - .globl __gc_init - .globl __gc_root_scan_stack - .globl __gc_stack_top - .globl __gc_stack_bottom - .extern init_pool - .extern gc_test_and_copy_root - .text + .globl __pre_gc + .globl __post_gc + .globl __gc_init + .globl __gc_root_scan_stack + .globl __gc_stack_top + .globl __gc_stack_bottom + .extern __init + .extern gc_test_and_mark_root + + .text __gc_init: - movl %ebp, __gc_stack_bottom - addl $4, __gc_stack_bottom - call __init - ret + movl %ebp, __gc_stack_bottom + addl $4, __gc_stack_bottom + call __init + ret // if __gc_stack_top is equal to 0 // then set __gc_stack_top to %ebp // else return __pre_gc: - pushl %eax - movl __gc_stack_top, %eax - cmpl $0, %eax - jne __pre_gc_2 - movl %ebp, %eax - // addl $8, %eax - movl %eax, __gc_stack_top + pushl %eax + movl __gc_stack_top, %eax + cmpl $0, %eax + jne __pre_gc_2 + movl %ebp, %eax + // addl $8, %eax + movl %eax, __gc_stack_top __pre_gc_2: - popl %eax - ret + popl %eax + ret // if __gc_stack_top has been set by the caller // (i.e. it is equal to its %ebp) // then set __gc_stack_top to 0 // else return __post_gc: - pushl %eax - movl __gc_stack_top, %eax - cmpl %eax, %ebp - jnz __post_gc2 - movl $0, __gc_stack_top + pushl %eax + movl __gc_stack_top, %eax + cmpl %eax, %ebp + jnz __post_gc2 + movl $0, __gc_stack_top __post_gc2: - popl %eax - ret + popl %eax + ret // Scan stack for roots // strting from __gc_stack_top // till __gc_stack_bottom __gc_root_scan_stack: - pushl %ebp - movl %esp, %ebp - pushl %ebx - pushl %edx - movl __gc_stack_top, %eax - jmp next + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %edx + movl __gc_stack_top, %eax + jmp next loop: movl (%eax), %ebx @@ -70,48 +66,48 @@ loop: // i.e. the following is not true: // __executable_start <= (%eax) <= __etext check11: - leal __executable_start, %edx - cmpl %ebx, %edx - jna check12 - jmp check21 + leal __executable_start, %edx + cmpl %ebx, %edx + jna check12 + jmp check21 check12: - leal __etext, %edx - cmpl %ebx, %edx - jnb next + leal __etext, %edx + cmpl %ebx, %edx + jnb next // check that it is not a pointer into the program stack // i.e. the following is not true: // __gc_stack_bottom <= (%eax) <= __gc_stack_top check21: - cmpl %ebx, __gc_stack_top - jna check22 - jmp loop2 + cmpl %ebx, __gc_stack_top + jna check22 + jmp loop2 check22: - cmpl %ebx, __gc_stack_bottom - jnb next + cmpl %ebx, __gc_stack_bottom + jnb next // check if it a valid pointer // i.e. the lastest bit is set to zero loop2: - andl $0x00000001, %ebx - jnz next + andl $0x00000001, %ebx + jnz next gc_run_t: - pushl %eax - pushl %eax - call gc_test_and_mark_root - addl $4, %esp - popl %eax + pushl %eax + pushl %eax + call gc_test_and_mark_root + addl $4, %esp + popl %eax next: - addl $4, %eax - cmpl %eax, __gc_stack_bottom - jne loop + addl $4, %eax + cmpl %eax, __gc_stack_bottom + jne loop returnn: - movl $0, %eax - popl %edx - popl %ebx - movl %ebp, %esp - popl %ebp - ret + movl $0, %eax + popl %edx + popl %ebx + movl %ebp, %esp + popl %ebp + ret diff --git a/runtime/runtime.c b/runtime/runtime.c index 45c7da16c..f439fa4ad 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -1,1441 +1,1417 @@ /* Runtime library */ -# define _GNU_SOURCE 1 +#define _GNU_SOURCE 1 -# include "runtime.h" -# include "runtime_common.h" -# include "gc.h" +#include "runtime.h" -# define __ENABLE_GC__ -# ifndef __ENABLE_GC__ -# define alloc malloc -# endif +#include "gc.h" +#include "runtime_common.h" + +#define __ENABLE_GC__ +#ifndef __ENABLE_GC__ +# define alloc malloc +#endif //# define DEBUG_PRINT 1 -# ifdef __ENABLE_GC__ +#ifdef __ENABLE_GC__ /* GC extern invariant for built-in functions */ -extern void __pre_gc (); +extern void __pre_gc (); extern void __post_gc (); -# else +#else -# define __pre_gc __pre_gc_subst -# define __post_gc __post_gc_subst +# define __pre_gc __pre_gc_subst +# define __post_gc __post_gc_subst -void __pre_gc_subst () {} -void __post_gc_subst () {} +void __pre_gc_subst () { } -# endif +void __post_gc_subst () { } + +#endif /* end */ static void vfailure (char *s, va_list args) { - fprintf (stderr, "*** FAILURE: "); - vfprintf (stderr, s, args); // vprintf (char *, va_list) <-> printf (char *, ...) - exit (255); + fprintf(stderr, "*** FAILURE: "); + vfprintf(stderr, s, args); // vprintf (char *, va_list) <-> printf (char *, ...) + exit(255); } void failure (char *s, ...) { - va_list args; + va_list args; - va_start (args, s); - vfailure (s, args); + va_start(args, s); + vfailure(s, args); } void Lassert (void *f, char *s, ...) { - if (!UNBOX(f)) { - va_list args; + if (!UNBOX(f)) { + va_list args; - va_start (args, s); - vfailure (s, args); - } + va_start(args, s); + vfailure(s, args); + } } -# define ASSERT_BOXED(memo, x) \ - 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) -# 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) +#define ASSERT_BOXED(memo, x) \ + 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) +#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) //extern void* alloc (size_t); -extern void* Bsexp (int n, ...); -extern int LtagHash (char*); +extern void *Bsexp (int n, ...); +extern int LtagHash (char *); void *global_sysargs; // Gets a raw data_header extern int LkindOf (void *p) { - if (UNBOXED(p)) return UNBOXED_TAG; + if (UNBOXED(p)) return UNBOXED_TAG; - return TAG(TO_DATA(p)->data_header); + return TAG(TO_DATA(p)->data_header); } // Compare sexprs tags extern int LcompareTags (void *p, void *q) { - data *pd, *qd; + data *pd, *qd; - ASSERT_BOXED ("compareTags, 0", p); - ASSERT_BOXED ("compareTags, 1", q); + ASSERT_BOXED("compareTags, 0", p); + ASSERT_BOXED("compareTags, 1", q); - pd = TO_DATA(p); - qd = TO_DATA(q); + pd = TO_DATA(p); + qd = TO_DATA(q); - if (TAG(pd->data_header) == SEXP_TAG && TAG(qd->data_header) == SEXP_TAG) { - return + if (TAG(pd->data_header) == SEXP_TAG && TAG(qd->data_header) == SEXP_TAG) { + return #ifndef DEBUG_PRINT - BOX((TO_SEXP(p)->tag) - (TO_SEXP(q)->tag)); + BOX((TO_SEXP(p)->tag) - (TO_SEXP(q)->tag)); #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 + return 0; // never happens } // Functional synonym for built-in operator ":"; -void* Ls__Infix_58 (void *p, void *q) { - void *res; +void *Ls__Infix_58 (void *p, void *q) { + void *res; - __pre_gc (); + __pre_gc(); - push_extra_root(&p); - push_extra_root(&q); - res = Bsexp (BOX(3), p, q, LtagHash ("cons")); //BOX(848787)); - pop_extra_root(&q); - pop_extra_root(&p); + push_extra_root(&p); + push_extra_root(&q); + res = Bsexp(BOX(3), p, q, LtagHash("cons")); //BOX(848787)); + pop_extra_root(&q); + pop_extra_root(&p); - __post_gc (); + __post_gc(); - return res; + return res; } // Functional synonym for built-in operator "!!"; int Ls__Infix_3333 (void *p, void *q) { - ASSERT_UNBOXED("captured !!:1", p); - ASSERT_UNBOXED("captured !!:2", q); + ASSERT_UNBOXED("captured !!:1", p); + ASSERT_UNBOXED("captured !!:2", q); - return BOX(UNBOX(p) || UNBOX(q)); + return BOX(UNBOX(p) || UNBOX(q)); } // Functional synonym for built-in operator "&&"; int Ls__Infix_3838 (void *p, void *q) { - ASSERT_UNBOXED("captured &&:1", p); - ASSERT_UNBOXED("captured &&:2", q); + ASSERT_UNBOXED("captured &&:1", p); + ASSERT_UNBOXED("captured &&:2", q); - return BOX(UNBOX(p) && UNBOX(q)); + return BOX(UNBOX(p) && UNBOX(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) { - ASSERT_UNBOXED("captured !=:1", p); - ASSERT_UNBOXED("captured !=:2", q); + ASSERT_UNBOXED("captured !=:1", p); + ASSERT_UNBOXED("captured !=:2", q); - return BOX(UNBOX(p) != UNBOX(q)); + return BOX(UNBOX(p) != UNBOX(q)); } // Functional synonym for built-in operator "<="; int Ls__Infix_6061 (void *p, void *q) { - ASSERT_UNBOXED("captured <=:1", p); - ASSERT_UNBOXED("captured <=:2", q); + ASSERT_UNBOXED("captured <=:1", p); + ASSERT_UNBOXED("captured <=:2", q); - return BOX(UNBOX(p) <= UNBOX(q)); + return BOX(UNBOX(p) <= UNBOX(q)); } // Functional synonym for built-in operator "<"; int Ls__Infix_60 (void *p, void *q) { - ASSERT_UNBOXED("captured <:1", p); - ASSERT_UNBOXED("captured <:2", q); + ASSERT_UNBOXED("captured <:1", p); + ASSERT_UNBOXED("captured <:2", q); - return BOX(UNBOX(p) < UNBOX(q)); + return BOX(UNBOX(p) < UNBOX(q)); } // Functional synonym for built-in operator ">="; int Ls__Infix_6261 (void *p, void *q) { - ASSERT_UNBOXED("captured >=:1", p); - ASSERT_UNBOXED("captured >=:2", q); + ASSERT_UNBOXED("captured >=:1", p); + ASSERT_UNBOXED("captured >=:2", q); - return BOX(UNBOX(p) >= UNBOX(q)); + return BOX(UNBOX(p) >= UNBOX(q)); } // Functional synonym for built-in operator ">"; int Ls__Infix_62 (void *p, void *q) { - ASSERT_UNBOXED("captured >:1", p); - ASSERT_UNBOXED("captured >:2", q); + ASSERT_UNBOXED("captured >:1", p); + ASSERT_UNBOXED("captured >:2", q); - return BOX(UNBOX(p) > UNBOX(q)); + return BOX(UNBOX(p) > UNBOX(q)); } // Functional synonym for built-in operator "+"; int Ls__Infix_43 (void *p, void *q) { - ASSERT_UNBOXED("captured +:1", p); - ASSERT_UNBOXED("captured +:2", q); + ASSERT_UNBOXED("captured +:1", p); + ASSERT_UNBOXED("captured +:2", q); - return BOX(UNBOX(p) + UNBOX(q)); + return BOX(UNBOX(p) + UNBOX(q)); } // Functional synonym for built-in operator "-"; int Ls__Infix_45 (void *p, void *q) { - if (UNBOXED(p)) { - ASSERT_UNBOXED("captured -:2", q); - return BOX(UNBOX(p) - UNBOX(q)); - } + if (UNBOXED(p)) { + ASSERT_UNBOXED("captured -:2", q); + return BOX(UNBOX(p) - UNBOX(q)); + } - ASSERT_BOXED("captured -:1", q); - return BOX(p - q); + ASSERT_BOXED("captured -:1", q); + return BOX(p - q); } // Functional synonym for built-in operator "*"; int Ls__Infix_42 (void *p, void *q) { - ASSERT_UNBOXED("captured *:1", p); - ASSERT_UNBOXED("captured *:2", q); + ASSERT_UNBOXED("captured *:1", p); + ASSERT_UNBOXED("captured *:2", q); - return BOX(UNBOX(p) * UNBOX(q)); + return BOX(UNBOX(p) * UNBOX(q)); } // Functional synonym for built-in operator "/"; int Ls__Infix_47 (void *p, void *q) { - ASSERT_UNBOXED("captured /:1", p); - ASSERT_UNBOXED("captured /:2", q); + ASSERT_UNBOXED("captured /:1", p); + ASSERT_UNBOXED("captured /:2", q); - return BOX(UNBOX(p) / UNBOX(q)); + return BOX(UNBOX(p) / UNBOX(q)); } // Functional synonym for built-in operator "%"; int Ls__Infix_37 (void *p, void *q) { - ASSERT_UNBOXED("captured %:1", p); - ASSERT_UNBOXED("captured %:2", q); + ASSERT_UNBOXED("captured %:1", p); + ASSERT_UNBOXED("captured %:2", q); - return BOX(UNBOX(p) % UNBOX(q)); + return BOX(UNBOX(p) % UNBOX(q)); } extern int Llength (void *p) { - ASSERT_BOXED(".length", p); - return BOX(LEN(TO_DATA(p)->data_header)); + ASSERT_BOXED(".length", p); + return BOX(LEN(TO_DATA(p)->data_header)); } -static char* chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'"; +static char *chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'"; -extern char* de_hash (int); +extern char *de_hash (int); extern int LtagHash (char *s) { - char *p; - int h = 0, limit = 0; + char *p; + int h = 0, limit = 0; - p = s; + p = s; - while (*p && limit++ <= 4) { - char *q = chars; - int pos = 0; + while (*p && limit++ <= 4) { + 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); + if (*q) h = (h << 6) | pos; + else failure("tagHash: character not found: %c\n", *p); - p++; - } + 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); + return BOX(h); } -char* de_hash (int n) { - // static char *chars = (char*) BOX (NULL); - static char buf[6] = {0,0,0,0,0,0}; - char *p = (char *) BOX (NULL); - p = &buf[5]; +char *de_hash (int n) { + // static char *chars = (char*) BOX (NULL); + static char buf[6] = {0, 0, 0, 0, 0, 0}; + char *p = (char *)BOX(NULL); + 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; + *p-- = 0; - while (n != 0) { + while (n != 0) { #ifdef DEBUG_PRINT - print_indent (); - printf ("char: %c\n", chars [n & 0x003F]); fflush (stdout); + print_indent(); + printf("char: %c\n", chars[n & 0x003F]); + fflush(stdout); #endif - *p-- = chars [n & 0x003F]; - n = n >> 6; - } + *p-- = chars[n & 0x003F]; + n = n >> 6; + } #ifdef DEBUG_PRINT - indent--; + indent--; #endif - return ++p; + return ++p; } typedef struct { - char *contents; - int ptr; - int len; + char *contents; + int ptr; + int len; } StringBuf; static StringBuf stringBuf; -# define STRINGBUF_INIT 128 +#define STRINGBUF_INIT 128 static void createStringBuf () { - stringBuf.contents = (char*) malloc (STRINGBUF_INIT); - memset(stringBuf.contents, 0, STRINGBUF_INIT); - stringBuf.ptr = 0; - stringBuf.len = STRINGBUF_INIT; + stringBuf.contents = (char *)malloc(STRINGBUF_INIT); + memset(stringBuf.contents, 0, STRINGBUF_INIT); + stringBuf.ptr = 0; + stringBuf.len = STRINGBUF_INIT; } -static void deleteStringBuf () { - free (stringBuf.contents); -} +static void deleteStringBuf () { free(stringBuf.contents); } static void extendStringBuf () { - int len = stringBuf.len << 1; + int len = stringBuf.len << 1; - stringBuf.contents = (char*) realloc (stringBuf.contents, len); - stringBuf.len = len; + stringBuf.contents = (char *)realloc(stringBuf.contents, len); + stringBuf.len = len; } static void vprintStringBuf (char *fmt, va_list args) { - int written = 0, - rest = 0; - char *buf = (char*) BOX(NULL); - va_list vsnargs; + int written = 0, rest = 0; + char *buf = (char *)BOX(NULL); + va_list vsnargs; - again: - va_copy (vsnargs, args); +again: + va_copy(vsnargs, args); - buf = &stringBuf.contents[stringBuf.ptr]; - rest = stringBuf.len - stringBuf.ptr; + buf = &stringBuf.contents[stringBuf.ptr]; + rest = stringBuf.len - stringBuf.ptr; - written = vsnprintf (buf, rest, fmt, vsnargs); + written = vsnprintf(buf, rest, fmt, vsnargs); - va_end(vsnargs); + va_end(vsnargs); - if (written >= rest) { - extendStringBuf (); - goto again; - } + if (written >= rest) { + extendStringBuf(); + goto again; + } - stringBuf.ptr += written; + stringBuf.ptr += written; } static void printStringBuf (char *fmt, ...) { - va_list args; + va_list args; - va_start (args, fmt); - vprintStringBuf (fmt, args); + va_start(args, fmt); + vprintStringBuf(fmt, args); } static void printValue (void *p) { - data *a = (data*) BOX(NULL); - int i = BOX(0); - if (UNBOXED(p)) { - printStringBuf ("%d", UNBOX(p)); - } else { - if (!is_valid_heap_pointer(p)) { - printStringBuf ("0x%x", p); - return; - } - - a = TO_DATA(p); - - switch (TAG(a->data_header)) { - case STRING_TAG: - printStringBuf ("\"%s\"", a->contents); - break; - - case CLOSURE_TAG: - printStringBuf ("data_header); i++) { - if (i) printValue ((void*)((int*) a->contents)[i]); - else printStringBuf ("0x%x", (void*)((int*) a->contents)[i]); - if (i != LEN(a->data_header) - 1) printStringBuf (", "); - } - printStringBuf (">"); - break; - - case ARRAY_TAG: - printStringBuf ("["); - for (i = 0; i < LEN(a->data_header); i++) { - printValue ((void*)((int*) a->contents)[i]); - if (i != LEN(a->data_header) - 1) printStringBuf (", "); - } - printStringBuf ("]"); - break; - - case SEXP_TAG: { - char * tag = de_hash (TO_SEXP(p)->tag); - if (strcmp (tag, "cons") == 0) { - data *b = a; - printStringBuf ("{"); - while (LEN(b->data_header)) { - printValue ((void*)((int*) b->contents)[0]); - b = (data*)((int*) b->contents)[1]; - if (! UNBOXED(b)) { - printStringBuf (", "); - b = TO_DATA(b); - } - else break; - } - printStringBuf ("}"); - } - else { - printStringBuf ("%s", tag); - if (LEN(a->data_header)) { - printStringBuf (" ("); - for (i = 0; i < LEN(a->data_header); i++) { - printValue ((void*)((int*) a->contents)[i]); - if (i != LEN(a->data_header) - 1) printStringBuf (", "); - } - printStringBuf (")"); - } - } - } - break; - - default: - printStringBuf ("*** invalid data_header: 0x%x ***", TAG(a->data_header)); - } + data *a = (data *)BOX(NULL); + int i = BOX(0); + if (UNBOXED(p)) { + printStringBuf("%d", UNBOX(p)); + } else { + if (!is_valid_heap_pointer(p)) { + printStringBuf("0x%x", p); + return; } + + a = TO_DATA(p); + + switch (TAG(a->data_header)) { + case STRING_TAG: printStringBuf("\"%s\"", a->contents); break; + + case CLOSURE_TAG: + printStringBuf("data_header); i++) { + if (i) printValue((void *)((int *)a->contents)[i]); + else printStringBuf("0x%x", (void *)((int *)a->contents)[i]); + if (i != LEN(a->data_header) - 1) printStringBuf(", "); + } + printStringBuf(">"); + break; + + case ARRAY_TAG: + printStringBuf("["); + for (i = 0; i < LEN(a->data_header); i++) { + printValue((void *)((int *)a->contents)[i]); + if (i != LEN(a->data_header) - 1) printStringBuf(", "); + } + printStringBuf("]"); + break; + + case SEXP_TAG: { + char *tag = de_hash(TO_SEXP(p)->tag); + if (strcmp(tag, "cons") == 0) { + data *b = a; + printStringBuf("{"); + while (LEN(b->data_header)) { + printValue((void *)((int *)b->contents)[0]); + b = (data *)((int *)b->contents)[1]; + if (!UNBOXED(b)) { + printStringBuf(", "); + b = TO_DATA(b); + } else break; + } + printStringBuf("}"); + } else { + printStringBuf("%s", tag); + if (LEN(a->data_header)) { + printStringBuf(" ("); + for (i = 0; i < LEN(a->data_header); i++) { + printValue((void *)((int *)a->contents)[i]); + if (i != LEN(a->data_header) - 1) printStringBuf(", "); + } + printStringBuf(")"); + } + } + } break; + + default: printStringBuf("*** invalid data_header: 0x%x ***", TAG(a->data_header)); + } + } } static void stringcat (void *p) { - data *a; - int i; + data *a; + int i; - if (UNBOXED(p)) ; - else { - a = TO_DATA(p); + if (UNBOXED(p)) + ; + else { + a = TO_DATA(p); - switch (TAG(a->data_header)) { - case STRING_TAG: - printStringBuf ("%s", a->contents); - break; + switch (TAG(a->data_header)) { + case STRING_TAG: printStringBuf("%s", a->contents); break; - case SEXP_TAG: { - char * tag = de_hash (TO_SEXP(p)->tag); + case SEXP_TAG: { + char *tag = de_hash(TO_SEXP(p)->tag); - if (strcmp (tag, "cons") == 0) { - data *b = a; + if (strcmp(tag, "cons") == 0) { + data *b = a; - while (LEN(b->data_header)) { - stringcat ((void*)((int*) b->contents)[0]); - b = (data*)((int*) b->contents)[1]; - if (! UNBOXED(b)) { - b = TO_DATA(b); - } - else break; - } - } - else printStringBuf ("*** non-list data_header: %s ***", tag); - } - break; + while (LEN(b->data_header)) { + stringcat((void *)((int *)b->contents)[0]); + b = (data *)((int *)b->contents)[1]; + if (!UNBOXED(b)) { + b = TO_DATA(b); + } else 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)); } + } } extern int Luppercase (void *v) { - ASSERT_UNBOXED("Luppercase:1", v); - return BOX(toupper ((int) UNBOX(v))); + ASSERT_UNBOXED("Luppercase:1", v); + return BOX(toupper((int)UNBOX(v))); } extern int Llowercase (void *v) { - ASSERT_UNBOXED("Llowercase:1", v); - return BOX(tolower ((int) UNBOX(v))); + ASSERT_UNBOXED("Llowercase:1", v); + return BOX(tolower((int)UNBOX(v))); } extern int LmatchSubString (char *subj, char *patt, int pos) { - data *p = TO_DATA(patt), *s = TO_DATA(subj); - int n; + data *p = TO_DATA(patt), *s = TO_DATA(subj); + int n; - ASSERT_STRING("matchSubString:1", subj); - ASSERT_STRING("matchSubString:2", patt); - ASSERT_UNBOXED("matchSubString:3", pos); + ASSERT_STRING("matchSubString:1", subj); + ASSERT_STRING("matchSubString:2", patt); + ASSERT_UNBOXED("matchSubString:3", pos); - n = LEN (p->data_header); + 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); + return BOX(strncmp(subj + UNBOX(pos), patt, n) == 0); } -extern void* Lsubstring (void *subj, int p, int l) { - data *d = TO_DATA(subj); - int pp = UNBOX (p), ll = UNBOX (l); +extern void *Lsubstring (void *subj, int p, int l) { + data *d = TO_DATA(subj); + int pp = UNBOX(p), ll = UNBOX(l); - ASSERT_STRING("substring:1", subj); - ASSERT_UNBOXED("substring:2", p); - ASSERT_UNBOXED("substring:3", l); + ASSERT_STRING("substring:1", subj); + ASSERT_UNBOXED("substring:2", p); + ASSERT_UNBOXED("substring:3", l); - if (pp + ll <= LEN(d->data_header)) { - data *r; + if (pp + ll <= LEN(d->data_header)) { + data *r; - __pre_gc (); + __pre_gc(); - push_extra_root (&subj); - r = (data*) alloc_string(ll); - pop_extra_root (&subj); + push_extra_root(&subj); + r = (data *)alloc_string(ll); + pop_extra_root(&subj); - strncpy (r->contents, (char*) subj + pp, ll); + strncpy(r->contents, (char *)subj + pp, ll); - __post_gc (); + __post_gc(); - return r->contents; - } + return r->contents; + } - failure ("substring: index out of bounds (position=%d, length=%d, \ - subject length=%d)", pp, ll, LEN(d->data_header)); + failure("substring: index out of bounds (position=%d, length=%d, \ + subject length=%d)", + pp, + ll, + LEN(d->data_header)); } extern struct re_pattern_buffer *Lregexp (char *regexp) { - regex_t *b = (regex_t*) malloc (sizeof (regex_t)); + regex_t *b = (regex_t *)malloc(sizeof(regex_t)); - /* printf ("regexp: %s,\test_small_tree_compaction%x\n", regexp, b); */ + /* printf ("regexp: %s,\test_small_tree_compaction%x\n", regexp, b); */ - memset (b, 0, sizeof (regex_t)); + memset(b, 0, sizeof(regex_t)); - int n = (int) re_compile_pattern (regexp, strlen (regexp), b); + int n = (int)re_compile_pattern(regexp, strlen(regexp), b); - if (n != 0) { - failure ("%", strerror (n)); - }; + if (n != 0) { failure("%", strerror(n)); }; - return b; + return b; } extern int LregexpMatch (struct re_pattern_buffer *b, char *s, int pos) { - int res; + int res; - ASSERT_BOXED("regexpMatch:1", b); - ASSERT_STRING("regexpMatch:2", s); - ASSERT_UNBOXED("regexpMatch:3", pos); + ASSERT_BOXED("regexpMatch:1", b); + ASSERT_STRING("regexpMatch:2", s); + ASSERT_UNBOXED("regexpMatch:3", pos); - res = re_match (b, s, LEN(TO_DATA(s)->data_header), UNBOX(pos), 0); + res = re_match(b, s, LEN(TO_DATA(s)->data_header), UNBOX(pos), 0); - /* 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) { - return BOX (res); - } + if (res) { return BOX(res); } - return BOX (res); + return BOX(res); } -extern void* Bstring (void*); +extern void *Bstring (void *); void *Lclone (void *p) { - data *obj; - sexp *sobj; - void* res; - int n; + data *obj; + sexp *sobj; + void *res; + int n; #ifdef DEBUG_PRINT - register int * ebp asm ("ebp"); - indent++; print_indent (); - printf ("Lclone arg: %p %p\n", &p, p); fflush (stdout); + register int *ebp asm("ebp"); + indent++; + print_indent(); + printf("Lclone arg: %p %p\n", &p, p); + fflush(stdout); #endif - __pre_gc (); + __pre_gc(); - if (UNBOXED(p)) return p; - else { - data *a = TO_DATA(p); - int t = TAG(a->data_header), l = LEN(a->data_header); + if (UNBOXED(p)) return p; + else { + data *a = TO_DATA(p); + int t = TAG(a->data_header), l = LEN(a->data_header); - push_extra_root (&p); - switch (t) { - case STRING_TAG: + push_extra_root(&p); + switch (t) { + case STRING_TAG: #ifdef DEBUG_PRINT - print_indent (); - printf ("Lclone: string1 &p=%p p=%p\n", &p, p); fflush (stdout); + print_indent(); + printf("Lclone: string1 &p=%p p=%p\n", &p, p); + fflush(stdout); #endif - res = Bstring (TO_DATA(p)->contents); + res = Bstring(TO_DATA(p)->contents); #ifdef DEBUG_PRINT - print_indent (); - printf ("Lclone: string2 %p %p\n", &p, p); fflush (stdout); + print_indent(); + printf("Lclone: string2 %p %p\n", &p, p); + fflush(stdout); #endif - break; + break; - case ARRAY_TAG: + case ARRAY_TAG: #ifdef DEBUG_PRINT - print_indent (); - printf ("Lclone: array &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout); + print_indent(); + 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)); - res = (void *) obj->contents; - break; - case CLOSURE_TAG: + obj = (data *)alloc_array(l); + memcpy(obj, TO_DATA(p), array_size(l)); + res = (void *)obj->contents; + break; + case CLOSURE_TAG: #ifdef DEBUG_PRINT - print_indent (); - printf ("Lclone: closure &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout); + print_indent(); + 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)); - res = (void*) (obj->contents); - break; + obj = (data *)alloc_closure(l); + memcpy(obj, TO_DATA(p), closure_size(l)); + res = (void *)(obj->contents); + break; - case SEXP_TAG: + 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; + 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); - } - pop_extra_root (&p); + 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 (); + __post_gc(); #ifdef DEBUG_PRINT - print_indent (); - printf ("Lclone ends2\n"); fflush (stdout); + print_indent(); + printf("Lclone ends2\n"); + fflush(stdout); indent--; #endif - return res; + 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_DEPTH 3 +#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; + if (depth > HASH_DEPTH) return acc; - if (UNBOXED(p)) return HASH_APPEND(acc, UNBOX(p)); - else if (is_valid_heap_pointer (p)) { - data *a = TO_DATA(p); - int t = TAG(a->data_header), l = LEN(a->data_header), i; + if (UNBOXED(p)) return HASH_APPEND(acc, UNBOX(p)); + else if (is_valid_heap_pointer(p)) { + data *a = TO_DATA(p); + int t = TAG(a->data_header), l = LEN(a->data_header), i; - acc = HASH_APPEND(acc, t); - acc = HASH_APPEND(acc, l); + acc = HASH_APPEND(acc, t); + acc = HASH_APPEND(acc, l); - switch (t) { - case STRING_TAG: { - char *p = a->contents; + switch (t) { + case STRING_TAG: { + char *p = a->contents; - while (*p) { - int n = (int) *p++; - acc = HASH_APPEND(acc, n); - } - - return acc; - } - - case CLOSURE_TAG: - acc = HASH_APPEND(acc, ((void**) a->contents)[0]); - i = 1; - break; - - case ARRAY_TAG: - i = 0; - break; - - case SEXP_TAG: { -#ifndef DEBUG_PRINT - int ta = TO_SEXP(p)->tag; -#else - int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header); -#endif - acc = HASH_APPEND(acc, ta); - i = 0; - break; - } - - default: - failure ("invalid data_header %d in hash *****\n", t); + while (*p) { + int n = (int)*p++; + acc = HASH_APPEND(acc, n); } - for (; icontents)[i]); - return acc; + } + + case CLOSURE_TAG: + acc = HASH_APPEND(acc, ((void **)a->contents)[0]); + i = 1; + break; + + case ARRAY_TAG: i = 0; break; + + case SEXP_TAG: { +#ifndef DEBUG_PRINT + int ta = TO_SEXP(p)->tag; +#else + int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header); +#endif + acc = HASH_APPEND(acc, ta); + i = 0; + break; + } + + default: failure("invalid data_header %d in hash *****\n", t); } - else return HASH_APPEND(acc, p); + + for (; i < l; i++) acc = inner_hash(depth + 1, acc, ((void **)a->contents)[i]); + + return acc; + } else return HASH_APPEND(acc, p); } -extern void* LstringInt (char *b) { - int n; - sscanf (b, "%d", &n); - return (void*) BOX(n); +extern void *LstringInt (char *b) { + int n; + sscanf(b, "%d", &n); + 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(p)) { + if (UNBOXED(q)) { return BOX(UNBOX(p) - UNBOX(q)); } - return -1; - } - else if (~UNBOXED(q)) { - return BOX(p - q); - } - else BOX(1); + return -1; + } else if (~UNBOXED(q)) { + return BOX(p - q); + } 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 (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 (is_valid_heap_pointer (p)) { - if (is_valid_heap_pointer (q)) { - data *a = TO_DATA(p), *b = TO_DATA(q); - int ta = TAG(a->data_header), tb = TAG(b->data_header); - int la = LEN(a->data_header), lb = LEN(b->data_header); - int i; + 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 (is_valid_heap_pointer(p)) { + if (is_valid_heap_pointer(q)) { + data *a = TO_DATA(p), *b = TO_DATA(q); + int ta = TAG(a->data_header), tb = TAG(b->data_header); + int la = LEN(a->data_header), lb = LEN(b->data_header); + int i; - COMPARE_AND_RETURN (ta, tb); + COMPARE_AND_RETURN(ta, tb); - switch (ta) { - case STRING_TAG: - return BOX(strcmp (a->contents, b->contents)); + switch (ta) { + case STRING_TAG: return BOX(strcmp(a->contents, b->contents)); - case CLOSURE_TAG: - COMPARE_AND_RETURN (((void**) a->contents)[0], ((void**) b->contents)[0]); - COMPARE_AND_RETURN (la, lb); - i = 1; - break; + case CLOSURE_TAG: + COMPARE_AND_RETURN(((void **)a->contents)[0], ((void **)b->contents)[0]); + COMPARE_AND_RETURN(la, lb); + i = 1; + break; - case ARRAY_TAG: - COMPARE_AND_RETURN (la, lb); - i = 0; - break; + case ARRAY_TAG: + COMPARE_AND_RETURN(la, lb); + i = 0; + break; - case SEXP_TAG: { + case SEXP_TAG: { #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 - 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); - i = 0; - break; - } + COMPARE_AND_RETURN(ta, tb); + COMPARE_AND_RETURN(la, lb); + i = 0; + break; + } - default: - failure ("invalid data_header %d in compare *****\n", ta); - } - - for (; icontents)[i], ((void**) b->contents)[i]); - if (c != BOX(0)) return BOX(c); - } - - return BOX(0); - } - else return BOX(-1); + default: failure("invalid data_header %d in compare *****\n", ta); } - else if (is_valid_heap_pointer (q)) return BOX(1); - else return BOX (p - q); - } + + for (; i < la; i++) { + int c = Lcompare(((void **)a->contents)[i], ((void **)b->contents)[i]); + if (c != BOX(0)) return BOX(c); + } + + return BOX(0); + } else return BOX(-1); + } else if (is_valid_heap_pointer(q)) return BOX(1); + else return BOX(p - q); + } } -extern void* Belem (void *p, int i) { - data *a = (data *)BOX(NULL); +extern void *Belem (void *p, int i) { + data *a = (data *)BOX(NULL); - ASSERT_BOXED(".elem:1", p); - ASSERT_UNBOXED(".elem:2", i); + ASSERT_BOXED(".elem:1", p); + ASSERT_UNBOXED(".elem:2", i); - a = TO_DATA(p); - i = UNBOX(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]; + return (void *)((int *)a->contents)[i]; } -extern void* LmakeArray (int length) { - data *r; - int n, *p; +extern void *LmakeArray (int length) { + data *r; + int n, *p; - ASSERT_UNBOXED("makeArray:1", length); + ASSERT_UNBOXED("makeArray:1", length); - __pre_gc (); + __pre_gc(); - n = UNBOX(length); - r = (data*) alloc_array(n); + n = UNBOX(length); + r = (data *)alloc_array(n); - p = (int*) r->contents; - while (n--) *p++ = BOX(0); + p = (int *)r->contents; + while (n--) *p++ = BOX(0); - __post_gc (); + __post_gc(); - return r->contents; + return r->contents; } -extern void* LmakeString (int length) { - int n = UNBOX(length); - data *r; +extern void *LmakeString (int length) { + int n = UNBOX(length); + data *r; - ASSERT_UNBOXED("makeString", length); + ASSERT_UNBOXED("makeString", length); - __pre_gc () ; + __pre_gc(); - r = (data*) alloc_string(n); // '\0' in the end of the string is taken into account + r = (data *)alloc_string(n); // '\0' in the end of the string is taken into account - __post_gc(); + __post_gc(); - return r->contents; + return r->contents; } -extern void* Bstring (void *p) { - int n = strlen (p); - void *s = NULL; +extern void *Bstring (void *p) { + int n = strlen(p); + void *s = NULL; - __pre_gc (); + __pre_gc(); #ifdef DEBUG_PRINT - indent++; print_indent (); - printf ("Bstring: call LmakeString %s %p %p %p %i\n", p, &p, p, s, n); - fflush(stdout); + indent++; + print_indent(); + printf("Bstring: call LmakeString %s %p %p %p %i\n", p, &p, p, s, n); + fflush(stdout); #endif - push_extra_root (&p); - s = LmakeString (BOX(n)); - pop_extra_root(&p); + push_extra_root(&p); + s = LmakeString(BOX(n)); + pop_extra_root(&p); #ifdef DEBUG_PRINT - print_indent (); - printf ("\tBstring: call strncpy: %p %p %p %i\n", &p, p, s, n); fflush(stdout); + print_indent(); + 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 + 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); - indent--; + print_indent(); + printf("\tBstring: ends\n"); + fflush(stdout); + indent--; #endif - __post_gc (); + __post_gc(); - return s; + return s; } -extern void* Lstringcat (void *p) { - void *s; +extern void *Lstringcat (void *p) { + void *s; - /* ASSERT_BOXED("stringcat", p); */ + /* ASSERT_BOXED("stringcat", p); */ - __pre_gc (); + __pre_gc(); - createStringBuf (); - stringcat (p); + createStringBuf(); + stringcat(p); - push_extra_root(&p); - s = Bstring (stringBuf.contents); - pop_extra_root(&p); + push_extra_root(&p); + s = Bstring(stringBuf.contents); + pop_extra_root(&p); - deleteStringBuf (); + deleteStringBuf(); - __post_gc (); + __post_gc(); - return s; + return s; } -extern void* Lstring (void *p) { - void *s = (void *) BOX (NULL); +extern void *Lstring (void *p) { + void *s = (void *)BOX(NULL); - __pre_gc () ; + __pre_gc(); - createStringBuf (); - printValue (p); + createStringBuf(); + printValue(p); - push_extra_root(&p); - s = Bstring (stringBuf.contents); - pop_extra_root(&p); + push_extra_root(&p); + s = Bstring(stringBuf.contents); + pop_extra_root(&p); - deleteStringBuf (); + deleteStringBuf(); - __post_gc (); + __post_gc(); - return s; + return s; } -extern void* Bclosure (int bn, void *entry, ...) { - va_list args; - int i, ai; - register int * ebp asm ("ebp"); - size_t *argss; - data *r; - int n = UNBOX(bn); +extern void *Bclosure (int bn, void *entry, ...) { + va_list args; + int i, ai; + register int *ebp asm("ebp"); + size_t *argss; + data *r; + int n = UNBOX(bn); - __pre_gc (); + __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; icontents)[0] = entry; + ((void **)r->contents)[0] = entry; - va_start(args, entry); + va_start(args, entry); - for (i = 0; icontents)[i+1] = ai; - } + for (i = 0; i < n; i++) { + ai = va_arg(args, int); + ((int *)r->contents)[i + 1] = ai; + } - va_end(args); + va_end(args); - __post_gc(); + __post_gc(); - argss--; - for (i = 0; icontents; + return r->contents; } -extern void* Barray (int bn, ...) { - va_list args; - int i, ai; - data *r; - int n = UNBOX(bn); +extern void *Barray (int bn, ...) { + va_list args; + int i, ai; + data *r; + int n = UNBOX(bn); - __pre_gc (); + __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); + r = (data *)alloc_array(n); - va_start(args, bn); + va_start(args, bn); - for (i = 0; icontents)[i] = ai; - } + for (i = 0; i < n; i++) { + ai = va_arg(args, int); + ((int *)r->contents)[i] = ai; + } - va_end(args); + va_end(args); - __post_gc(); + __post_gc(); #ifdef DEBUG_PRINT - indent--; + indent--; #endif - return r->contents; + return r->contents; } #ifdef DEBUG_VERSION extern memory_chunk heap; #endif -extern void* Bsexp (int bn, ...) { - va_list args; - int i; - int ai; - size_t *p; - sexp *r; - data *d; - int n = UNBOX(bn); +extern void *Bsexp (int bn, ...) { + va_list args; + int i; + int ai; + size_t *p; + sexp *r; + data *d; + int n = UNBOX(bn); - __pre_gc () ; + __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); - d = &(r->contents); - r->tag = 0; + int fields_cnt = n - 1; + r = (sexp *)alloc_sexp(fields_cnt); + d = &(r->contents); + r->tag = 0; - va_start(args, bn); + va_start(args, bn); - for (i=0; icontents)[i] = ai; - } + p = (size_t *)ai; + ((int *)d->contents)[i] = ai; + } - r->tag = UNBOX(va_arg(args, int)); + r->tag = UNBOX(va_arg(args, int)); #ifdef DEBUG_PRINT - r->data_header = SEXP_TAG | ((r->data_header) << 3); - print_indent (); - printf("Bsexp: ends\n"); fflush (stdout); - indent--; + r->data_header = SEXP_TAG | ((r->data_header) << 3); + print_indent(); + printf("Bsexp: ends\n"); + fflush(stdout); + indent--; #endif - va_end(args); + va_end(args); - __post_gc(); + __post_gc(); - return d->contents; + return d->contents; } extern int Btag (void *d, int t, int n) { - data *r; + data *r; - if (UNBOXED(d)) return BOX(0); - else { - r = TO_DATA(d); + if (UNBOXED(d)) return BOX(0); + 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 - } + } } -int get_tag(data *d) { -// printf("%") - return TAG(d->data_header); +int get_tag (data *d) { + // printf("%") + 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; + data *r; - if (UNBOXED(d)) return BOX(0); - else { - r = TO_DATA(d); - return BOX(get_tag(r) == ARRAY_TAG && get_len(r) == UNBOX(n)); - } + if (UNBOXED(d)) return BOX(0); + else { + r = TO_DATA(d); + return BOX(get_tag(r) == ARRAY_TAG && get_len(r) == UNBOX(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); + ASSERT_STRING(".string_patt:2", y); - if (UNBOXED(x)) return BOX(0); - else { - rx = TO_DATA(x); ry = TO_DATA(y); + if (UNBOXED(x)) return BOX(0); + else { + 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); - return BOX(strcmp (rx->contents, ry->contents) == 0 ? 1 : 0); // TODO: ??? - } + return BOX(strcmp(rx->contents, ry->contents) == 0 ? 1 : 0); // TODO: ??? + } } extern int Bclosure_tag_patt (void *x) { - if (UNBOXED(x)) return BOX(0); + if (UNBOXED(x)) return BOX(0); - 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) { - if (UNBOXED(x)) return BOX(0); + if (UNBOXED(x)) return BOX(0); - return BOX(TAG(TO_DATA(x)->data_header) == ARRAY_TAG); + return BOX(TAG(TO_DATA(x)->data_header) == ARRAY_TAG); } extern int Bstring_tag_patt (void *x) { - if (UNBOXED(x)) return BOX(0); + if (UNBOXED(x)) return BOX(0); - return BOX(TAG(TO_DATA(x)->data_header) == STRING_TAG); + return BOX(TAG(TO_DATA(x)->data_header) == STRING_TAG); } extern int Bsexp_tag_patt (void *x) { - if (UNBOXED(x)) return BOX(0); + if (UNBOXED(x)) return BOX(0); - return BOX(TAG(TO_DATA(x)->data_header) == SEXP_TAG); + return BOX(TAG(TO_DATA(x)->data_header) == SEXP_TAG); } -extern void* Bsta (void *v, int i, void *x) { - if (UNBOXED(i)) { - ASSERT_BOXED(".sta:3", x); - // ASSERT_UNBOXED(".sta:2", i); +extern void *Bsta (void *v, int i, void *x) { + if (UNBOXED(i)) { + ASSERT_BOXED(".sta:3", x); + // ASSERT_UNBOXED(".sta:2", i); - if (TAG(TO_DATA(x)->data_header) == STRING_TAG)((char*) x)[UNBOX(i)] = (char) UNBOX(v); - else ((int*) x)[UNBOX(i)] = (int) v; - - return v; - } - - * (void**) x = v; + if (TAG(TO_DATA(x)->data_header) == STRING_TAG) ((char *)x)[UNBOX(i)] = (char)UNBOX(v); + else ((int *)x)[UNBOX(i)] = (int)v; return v; + } + + *(void **)x = v; + + return v; } static void fix_unboxed (char *s, va_list va) { - size_t *p = (size_t*)va; - int i = 0; + size_t *p = (size_t *)va; + int i = 0; - while (*s) { - if (*s == '%') { - size_t n = p [i]; - if (UNBOXED (n)) { - p[i] = UNBOX(n); - } - i++; - } - s++; + while (*s) { + if (*s == '%') { + size_t n = p[i]; + if (UNBOXED(n)) { p[i] = UNBOX(n); } + i++; } + s++; + } } extern void Lfailure (char *s, ...) { - va_list args; + va_list args; - va_start (args, s); - fix_unboxed (s, args); - vfailure (s, args); + va_start(args, s); + fix_unboxed(s, args); + vfailure(s, args); } 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); + createStringBuf(); + printValue(v); + failure("match failure at %s:%d:%d, value '%s'\n", + fname, + UNBOX(line), + UNBOX(col), + stringBuf.contents); } -extern void* /*Lstrcat*/ Li__Infix_4343 (void *a, void *b) { - data *da = (data*) BOX (NULL); - data *db = (data*) BOX (NULL); - data *d = (data*) BOX (NULL); +extern void * /*Lstrcat*/ Li__Infix_4343 (void *a, void *b) { + data *da = (data *)BOX(NULL); + data *db = (data *)BOX(NULL); + data *d = (data *)BOX(NULL); - ASSERT_STRING("++:1", a); - ASSERT_STRING("++:2", b); + ASSERT_STRING("++:1", a); + ASSERT_STRING("++:2", b); - da = TO_DATA(a); - db = TO_DATA(b); + da = TO_DATA(a); + db = TO_DATA(b); - __pre_gc () ; + __pre_gc(); - push_extra_root (&a); - push_extra_root (&b); - d = alloc_string(LEN(da->data_header) + LEN(db->data_header)); - pop_extra_root (&b); - pop_extra_root (&a); + push_extra_root(&a); + push_extra_root(&b); + d = alloc_string(LEN(da->data_header) + LEN(db->data_header)); + pop_extra_root(&b); + pop_extra_root(&a); - da = TO_DATA(a); - db = TO_DATA(b); + da = TO_DATA(a); + db = TO_DATA(b); - strncpy (d->contents , da->contents, LEN(da->data_header)); - strncpy (d->contents + LEN(da->data_header), db->contents, LEN(db->data_header)); + strncpy(d->contents, da->contents, LEN(da->data_header)); + strncpy(d->contents + LEN(da->data_header), db->contents, LEN(db->data_header)); - d->contents[LEN(da->data_header) + LEN(db->data_header)] = 0; + d->contents[LEN(da->data_header) + LEN(db->data_header)] = 0; - __post_gc(); + __post_gc(); - return d->contents; + return d->contents; } -extern void* Lsprintf (char * fmt, ...) { - va_list args; - void *s; +extern void *Lsprintf (char *fmt, ...) { + va_list args; + void *s; - ASSERT_STRING("sprintf:1", fmt); + ASSERT_STRING("sprintf:1", fmt); - va_start (args, fmt); - fix_unboxed (fmt, args); + va_start(args, fmt); + fix_unboxed(fmt, args); - createStringBuf (); + createStringBuf(); - vprintStringBuf (fmt, args); + vprintStringBuf(fmt, args); - __pre_gc (); + __pre_gc(); - push_extra_root ((void**)&fmt); - s = Bstring (stringBuf.contents); - pop_extra_root ((void**)&fmt); + push_extra_root((void **)&fmt); + s = Bstring(stringBuf.contents); + pop_extra_root((void **)&fmt); - __post_gc (); + __post_gc(); - deleteStringBuf (); + deleteStringBuf(); - return s; + return s; } -extern void* LgetEnv (char *var) { - char *e = getenv (var); - void *s; +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 (); + __pre_gc(); - s = Bstring (e); + s = Bstring(e); - __post_gc (); + __post_gc(); - return s; + 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); + va_list args = (va_list)BOX(NULL); - ASSERT_BOXED("fprintf:1", f); - ASSERT_STRING("fprintf:2", s); + ASSERT_BOXED("fprintf:1", f); + ASSERT_STRING("fprintf:2", s); - va_start (args, s); - fix_unboxed (s, args); + 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, ...) { - va_list args = (va_list) BOX (NULL); + va_list args = (va_list)BOX(NULL); - ASSERT_STRING("printf:1", s); + ASSERT_STRING("printf:1", s); - va_start (args, s); - fix_unboxed (s, args); + 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); + fflush(stdout); } -extern FILE* Lfopen (char *f, char *m) { - FILE* h; +extern FILE *Lfopen (char *f, char *m) { + FILE *h; - ASSERT_STRING("fopen:1", f); - ASSERT_STRING("fopen:2", m); + ASSERT_STRING("fopen:1", f); + ASSERT_STRING("fopen:2", m); - h = fopen (f, 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)); + failure("fopen (\"%s\", \"%s\"): %s, %s, %s\n", f, m, strerror(errno)); } extern void Lfclose (FILE *f) { - ASSERT_BOXED("fclose", f); + ASSERT_BOXED("fclose", f); - fclose (f); + fclose(f); } -extern void* LreadLine () { - char *buf; +extern void *LreadLine () { + char *buf; - if (scanf ("%m[^\n]", &buf) == 1) { - void * s = Bstring (buf); + if (scanf("%m[^\n]", &buf) == 1) { + void *s = Bstring(buf); - getchar (); + getchar(); - free (buf); + free(buf); + return s; + } + + if (errno != 0) failure("readLine (): %s\n", strerror(errno)); + + return (void *)BOX(0); +} + +extern void *Lfread (char *fname) { + FILE *f; + + ASSERT_STRING("fread", fname); + + f = fopen(fname, "r"); + + if (f) { + if (fseek(f, 0l, SEEK_END) >= 0) { + long size = ftell(f); + void *s = LmakeString(BOX(size)); + + rewind(f); + + if (fread(s, 1, size, f) == size) { + fclose(f); return s; + } } + } - if (errno != 0) - failure ("readLine (): %s\n", strerror (errno)); - - return (void*) BOX (0); -} - -extern void* Lfread (char *fname) { - FILE *f; - - ASSERT_STRING("fread", fname); - - f = fopen (fname, "r"); - - if (f) { - if (fseek (f, 0l, SEEK_END) >= 0) { - long size = ftell (f); - void *s = LmakeString (BOX(size)); - - rewind (f); - - if (fread (s, 1, size, f) == size) { - fclose (f); - return s; - } - } - } - - failure ("fread (\"%s\"): %s\n", fname, strerror (errno)); + failure("fread (\"%s\"): %s\n", fname, strerror(errno)); } extern void Lfwrite (char *fname, char *contents) { - FILE *f; + FILE *f; - ASSERT_STRING("fwrite:1", fname); - ASSERT_STRING("fwrite:2", contents); + ASSERT_STRING("fwrite:1", fname); + ASSERT_STRING("fwrite:2", contents); - f = fopen (fname, "w"); + f = fopen(fname, "w"); - if (f) { - if (fprintf (f, "%s", contents) < 0); - else { - fclose (f); - return; - } + if (f) { + if (fprintf(f, "%s", contents) < 0) + ; + else { + fclose(f); + return; } + } - failure ("fwrite (\"%s\"): %s\n", fname, strerror (errno)); + failure("fwrite (\"%s\"): %s\n", fname, strerror(errno)); } -extern void* Lfexists (char *fname) { - FILE *f; +extern void *Lfexists (char *fname) { + FILE *f; - ASSERT_STRING("fexists", fname); + ASSERT_STRING("fexists", fname); - f = fopen (fname, "r"); + f = fopen(fname, "r"); - if (f) return (void*) BOX(1); // (void*) cast? + if (f) return (void *)BOX(1); // (void*) cast? - return (void*) BOX(0); // (void*) cast? + 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 () { - int result = BOX(0); + int result = BOX(0); - printf ("> "); - fflush (stdout); - scanf ("%d", &result); + printf("> "); + fflush(stdout); + scanf("%d", &result); - return BOX(result); + return BOX(result); } /* Lwrite is an implementation of the "write" construct */ extern int Lwrite (int n) { - printf ("%d\n", UNBOX(n)); - fflush (stdout); + printf("%d\n", UNBOX(n)); + fflush(stdout); - return 0; + return 0; } extern int Lrandom (int n) { - ASSERT_UNBOXED("Lrandom, 0", 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)); + return BOX(random() % UNBOX(n)); } extern int Ltime () { - struct timespec t; + struct timespec t; - clock_gettime (CLOCK_MONOTONIC_RAW, &t); + clock_gettime(CLOCK_MONOTONIC_RAW, &t); - return BOX(t.tv_sec * 1000000 + t.tv_nsec / 1000); + return BOX(t.tv_sec * 1000000 + t.tv_nsec / 1000); } extern void set_args (int argc, char *argv[]) { - data *a; - int n = argc, *p = NULL; - int i; + data *a; + int n = argc, *p = NULL; + int i; - __pre_gc (); + __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 - p = LmakeArray (BOX(n)); - push_extra_root ((void**)&p); + p = LmakeArray(BOX(n)); + push_extra_root((void **)&p); - for (i=0; i\n", i, &p, p); fflush(stdout); + print_indent(); + printf("set_args: iteration %i %p %p ->\n", i, &p, p); + fflush(stdout); #endif - ((int*)p) [i] = (int) Bstring (argv[i]); + ((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); + print_indent(); + printf("set_args: iteration %i <- %p %p\n", i, &p, p); + fflush(stdout); #endif - } + } - pop_extra_root ((void**)&p); - __post_gc (); + pop_extra_root((void **)&p); + __post_gc(); - global_sysargs = p; - push_extra_root ((void**)&global_sysargs); + global_sysargs = p; + push_extra_root((void **)&global_sysargs); #ifdef DEBUG_PRINT - print_indent (); - printf ("set_args: end\n", n, &p, p); fflush(stdout); + print_indent(); + 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; } diff --git a/runtime/runtime.h b/runtime/runtime.h index 677429fd7..346624e2b 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -1,21 +1,20 @@ -# ifndef __LAMA_RUNTIME__ -# define __LAMA_RUNTIME__ +#ifndef __LAMA_RUNTIME__ +#define __LAMA_RUNTIME__ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -# define WORD_SIZE (CHAR_BIT * sizeof(int)) +#define WORD_SIZE (CHAR_BIT * sizeof(int)) void failure (char *s, ...); -# endif +#endif diff --git a/runtime/runtime_common.h b/runtime/runtime_common.h index 537a8ac44..664b9e9e0 100644 --- a/runtime/runtime_common.h +++ b/runtime/runtime_common.h @@ -5,67 +5,65 @@ // this flag makes GC behavior a bit different for testing purposes. //#define DEBUG_VERSION -# define STRING_TAG 0x00000001 +#define STRING_TAG 0x00000001 //# define STRING_TAG 0x00000000 -# define ARRAY_TAG 0x00000003 +#define ARRAY_TAG 0x00000003 //# define ARRAY_TAG 0x00000002 -# define SEXP_TAG 0x00000005 +#define SEXP_TAG 0x00000005 //# define SEXP_TAG 0x00000004 -# define CLOSURE_TAG 0x00000007 +#define CLOSURE_TAG 0x00000007 //# define CLOSURE_TAG 0x00000006 -# define UNBOXED_TAG 0x00000009 // Not actually a data_header; used to return from LkindOf +#define UNBOXED_TAG 0x00000009 // Not actually a data_header; used to return from LkindOf -# define LEN(x) ((x & 0xFFFFFFF8) >> 3) -# define TAG(x) (x & 0x00000007) +#define LEN(x) ((x & 0xFFFFFFF8) >> 3) +#define TAG(x) (x & 0x00000007) //# define TAG(x) (x & 0x00000006) +#define SEXP_ONLY_HEADER_SZ (2 * sizeof(int)) -# define SEXP_ONLY_HEADER_SZ (2 * sizeof(int)) - -# ifndef DEBUG_VERSION -# define DATA_HEADER_SZ (sizeof(size_t) + sizeof(int)) -# else -# define DATA_HEADER_SZ (sizeof(size_t) + sizeof(size_t) + sizeof(int)) +#ifndef DEBUG_VERSION +# define DATA_HEADER_SZ (sizeof(size_t) + sizeof(int)) +#else +# define DATA_HEADER_SZ (sizeof(size_t) + sizeof(size_t) + sizeof(int)) #endif -# define MEMBER_SIZE sizeof(int) +#define MEMBER_SIZE sizeof(int) -# define TO_DATA(x) ((data*)((char*)(x)-DATA_HEADER_SZ)) -# define TO_SEXP(x) ((sexp*)((char*)(x)-DATA_HEADER_SZ-SEXP_ONLY_HEADER_SZ)) +#define TO_DATA(x) ((data *)((char *)(x)-DATA_HEADER_SZ)) +#define TO_SEXP(x) ((sexp *)((char *)(x)-DATA_HEADER_SZ - SEXP_ONLY_HEADER_SZ)) -# define UNBOXED(x) (((int) (x)) & 0x0001) -# define UNBOX(x) (((int) (x)) >> 1) -# define BOX(x) ((((int) (x)) << 1) | 0x0001) +#define UNBOXED(x) (((int)(x)) & 0x0001) +#define UNBOX(x) (((int)(x)) >> 1) +#define BOX(x) ((((int)(x)) << 1) | 0x0001) -# define BYTES_TO_WORDS(bytes) (((bytes) - 1) / sizeof(size_t) + 1) -# define WORDS_TO_BYTES(words) ((words) * sizeof(size_t)) +#define BYTES_TO_WORDS(bytes) (((bytes)-1) / sizeof(size_t) + 1) +#define WORDS_TO_BYTES(words) ((words) * sizeof(size_t)) // CAREFUL WITH DOUBLE EVALUATION! #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) - int data_header; + // 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) + int data_header; #ifdef DEBUG_VERSION - size_t id; + size_t id; #endif - // last bit is used as MARK-BIT, the rest are used to store address where object should move - // last bit can be used because due to alignment we can assume that last two bits are always 0's - size_t forward_address; - char contents[0]; + // last bit is used as MARK-BIT, the rest are used to store address where object should move + // last bit can be used because due to alignment we can assume that last two bits are always 0's + size_t forward_address; + char contents[0]; } data; typedef struct { - // duplicates contents.data_header in order to be able to understand if it is s-exp during iteration over heap - int sexp_header; - // stores hashed s-expression constructor name - int tag; - data contents; + // duplicates contents.data_header in order to be able to understand if it is s-exp during iteration over heap + int sexp_header; + // stores hashed s-expression constructor name + int tag; + data contents; } sexp; -#endif \ No newline at end of file +#endif diff --git a/runtime/test_main.c b/runtime/test_main.c index 558abbf80..bd3f8312d 100644 --- a/runtime/test_main.c +++ b/runtime/test_main.c @@ -1,273 +1,275 @@ -#include -#include -#include -#include #include "gc.h" #include "runtime_common.h" +#include +#include +#include +#include + #ifdef DEBUG_VERSION // function from runtime that maps string to int value extern int LtagHash (char *s); -extern void* Bsexp (int n, ...); -extern void* Barray (int bn, ...); -extern void* Bstring (void*); -extern void* Bclosure (int bn, void *entry, ...); +extern void *Bsexp (int n, ...); +extern void *Barray (int bn, ...); +extern void *Bstring (void *); +extern void *Bclosure (int bn, void *entry, ...); extern size_t __gc_stack_top, __gc_stack_bottom; -void test_correct_structure_sizes(void) { - // something like induction base - assert((array_size(0) == get_header_size(ARRAY))); - assert((string_size(0) == get_header_size(STRING) + 1)); // +1 is because of '\0' - assert((sexp_size(0) == get_header_size(SEXP))); - assert((closure_size(0) == get_header_size(CLOSURE))); +void test_correct_structure_sizes (void) { + // something like induction base + assert((array_size(0) == get_header_size(ARRAY))); + assert((string_size(0) == get_header_size(STRING) + 1)); // +1 is because of '\0' + assert((sexp_size(0) == get_header_size(SEXP))); + assert((closure_size(0) == get_header_size(CLOSURE))); - // just check correctness for some small sizes - for (int k = 1; k < 20; ++k) { - assert((array_size(k) == get_header_size(ARRAY) + sizeof (int) * k)); - assert((string_size(k) == get_header_size(STRING) + k + 1)); - assert((sexp_size(k) == get_header_size(SEXP) + sizeof (int) * k)); - assert((closure_size(k) == get_header_size(CLOSURE) + sizeof (int) * k)); - } + // just check correctness for some small sizes + for (int k = 1; k < 20; ++k) { + assert((array_size(k) == get_header_size(ARRAY) + sizeof(int) * k)); + assert((string_size(k) == get_header_size(STRING) + k + 1)); + assert((sexp_size(k) == get_header_size(SEXP) + sizeof(int) * k)); + assert((closure_size(k) == get_header_size(CLOSURE) + sizeof(int) * k)); + } } -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" +# include "virt_stack.h" -virt_stack* init_test() { - __init(); - virt_stack *st = vstack_create(); - vstack_init(st); - __gc_stack_bottom = (size_t) vstack_top(st); - return st; +virt_stack *init_test () { + __init(); + virt_stack *st = vstack_create(); + vstack_init(st); + __gc_stack_bottom = (size_t)vstack_top(st); + return st; } -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); - __gc_stack_top = 0; +void cleanup_test (virt_stack *st) { + vstack_destruct(st); + __shutdown(); } -void test_simple_string_alloc(void) { - virt_stack *st = init_test(); - - 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")); - - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); - - cleanup_test(st); +void force_gc_cycle (virt_stack *st) { + __gc_stack_top = (size_t)vstack_top(st) - 4; + gc_alloc(0); + __gc_stack_top = 0; } -void test_simple_array_alloc(void) { - virt_stack* st = init_test(); +void test_simple_string_alloc (void) { + virt_stack *st = init_test(); - // allocate array [ BOX(1) ] and push it onto the stack - vstack_push(st, call_runtime_function(vstack_top(st) - 4, Barray, 2, BOX(1), BOX(1))); + for (int i = 0; i < 5; ++i) { vstack_push(st, BOX(i)); } - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); + vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "abc")); - cleanup_test(st); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); + + cleanup_test(st); } -void test_simple_sexp_alloc(void) { - virt_stack* st = init_test(); +void test_simple_array_alloc (void) { + virt_stack *st = init_test(); - // 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"))); + // allocate array [ BOX(1) ] and push it onto the stack + vstack_push(st, call_runtime_function(vstack_top(st) - 4, Barray, 2, BOX(1), BOX(1))); - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); - cleanup_test(st); + cleanup_test(st); } -void test_simple_closure_alloc(void) { - virt_stack* st = init_test(); +void test_simple_sexp_alloc (void) { + virt_stack *st = init_test(); - // allocate closure with boxed captured value and push it onto the stack - vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bclosure, 3, BOX(1), NULL, BOX(1))); + // 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"))); - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); - cleanup_test(st); + cleanup_test(st); } -void test_single_object_allocation_with_collection_virtual_stack(void) { - virt_stack *st = init_test(); +void test_simple_closure_alloc (void) { + virt_stack *st = init_test(); - vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + // allocate closure with boxed captured value and push it onto the stack + vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bclosure, 3, BOX(1), NULL, BOX(1))); - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); - cleanup_test(st); + cleanup_test(st); } -void test_garbage_is_reclaimed(void) { - virt_stack *st = init_test(); +void test_single_object_allocation_with_collection_virtual_stack (void) { + virt_stack *st = init_test(); - 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); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 0)); - - cleanup_test(st); + cleanup_test(st); } -void test_alive_are_not_reclaimed(void) { - virt_stack *st = init_test(); +void test_garbage_is_reclaimed (void) { + virt_stack *st = init_test(); - vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - force_gc_cycle(st); + force_gc_cycle(st); - const int N = 10; - int ids[N]; - size_t alive = objects_snapshot(ids, N); - assert((alive == 1)); + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 0)); - cleanup_test(st); + cleanup_test(st); } -void test_small_tree_compaction(void) { - virt_stack *st = init_test(); - // this one will increase heap size - call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaa"); +void test_alive_are_not_reclaimed (void) { + virt_stack *st = init_test(); - 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"))); - force_gc_cycle(st); - const int SZ = 10; - int ids[SZ]; - size_t alive = objects_snapshot(ids, SZ); - assert((alive == 3)); + vstack_push(st, + call_runtime_function( + vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); - // check that order is indeed preserved - for (int i = 0; i < alive - 1; ++i) { - assert((ids[i] < ids[i + 1])); - } - cleanup_test(st); + force_gc_cycle(st); + + const int N = 10; + int ids[N]; + size_t alive = objects_snapshot(ids, N); + assert((alive == 1)); + + cleanup_test(st); +} + +void test_small_tree_compaction (void) { + virt_stack *st = init_test(); + // this one will increase heap size + call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaa"); + + 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"))); + force_gc_cycle(st); + const int SZ = 10; + int ids[SZ]; + size_t alive = objects_snapshot(ids, SZ); + assert((alive == 3)); + + // check that order is indeed preserved + for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); } + cleanup_test(st); } extern size_t cur_id; -size_t generate_random_obj_forest(virt_stack *st, int cnt, int seed) { - srand(seed); - int cur_sz = 0; - size_t alive = 0; - while (cnt) { - --cnt; - if (cur_sz == 0) { - vstack_push(st, BOX(1)); - ++cur_sz; - continue; - } - - 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]); - } - size_t obj; - - if (rand() % 2) { - 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; - } - } - ++cur_sz; +size_t generate_random_obj_forest (virt_stack *st, int cnt, int seed) { + srand(seed); + int cur_sz = 0; + size_t alive = 0; + while (cnt) { + --cnt; + if (cur_sz == 0) { + vstack_push(st, BOX(1)); + ++cur_sz; + continue; } - force_gc_cycle(st); - return alive; + + 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]); } + size_t obj; + + if (rand() % 2) { + 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; } + } + ++cur_sz; + } + force_gc_cycle(st); + return alive; } -void run_stress_test_random_obj_forest(int seed) { - virt_stack *st = init_test(); +void run_stress_test_random_obj_forest (int seed) { + virt_stack *st = init_test(); - const int SZ = 100000; + const int SZ = 100000; - size_t expectedAlive = generate_random_obj_forest(st, SZ, seed); + size_t expectedAlive = generate_random_obj_forest(st, SZ, seed); - int ids[SZ]; - size_t alive = objects_snapshot(ids, SZ); - assert(alive == expectedAlive); + int ids[SZ]; + size_t alive = objects_snapshot(ids, SZ); + assert(alive == expectedAlive); - // check that order is indeed preserved - for (int i = 0; i < alive - 1; ++i) { - assert((ids[i] < ids[i + 1])); - } + // check that order is indeed preserved + for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); } - cleanup_test(st); + cleanup_test(st); } #endif #include -int main(int argc, char ** argv) { +int main (int argc, char **argv) { #ifdef DEBUG_VERSION - no_gc_tests(); + no_gc_tests(); - test_simple_string_alloc(); - test_simple_array_alloc(); - test_simple_sexp_alloc(); - test_simple_closure_alloc(); - test_single_object_allocation_with_collection_virtual_stack(); - test_garbage_is_reclaimed(); - test_alive_are_not_reclaimed(); - test_small_tree_compaction(); + test_simple_string_alloc(); + test_simple_array_alloc(); + test_simple_sexp_alloc(); + test_simple_closure_alloc(); + test_single_object_allocation_with_collection_virtual_stack(); + test_garbage_is_reclaimed(); + test_alive_are_not_reclaimed(); + test_small_tree_compaction(); - time_t start, end; - double diff; - time(&start); - // stress test - 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); + time_t start, end; + double diff; + time(&start); + // stress test + 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); #endif -} \ No newline at end of file +} diff --git a/runtime/virt_stack.c b/runtime/virt_stack.c index 532b4a7fd..2e2e7a9d0 100644 --- a/runtime/virt_stack.c +++ b/runtime/virt_stack.c @@ -1,45 +1,34 @@ #include "virt_stack.h" + #include -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_init (virt_stack *st) { + st->cur = RUNTIME_VSTACK_SIZE; + st->buf[st->cur] = 0; } -void vstack_destruct(virt_stack *st) { - free(st); +void vstack_push (virt_stack *st, size_t value) { + if (st->cur == 0) { assert(0); } + --st->cur; + st->buf[st->cur] = value; } -void vstack_init(virt_stack *st) { - st->cur = RUNTIME_VSTACK_SIZE; - st->buf[st->cur] = 0; +size_t vstack_pop (virt_stack *st) { + if (st->cur == RUNTIME_VSTACK_SIZE) { assert(0); } + size_t value = st->buf[st->cur]; + ++st->cur; + return value; } -void vstack_push(virt_stack *st, size_t value) { - if (st->cur == 0) { - assert(0); - } - --st->cur; - st->buf[st->cur] = value; -} +void *vstack_top (virt_stack *st) { return st->buf + st->cur; } -size_t vstack_pop(virt_stack *st) { - if (st->cur == RUNTIME_VSTACK_SIZE) { - assert(0); - } - size_t value = st->buf[st->cur]; - ++st->cur; - return value; -} +size_t vstack_size (virt_stack *st) { return RUNTIME_VSTACK_SIZE - 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_kth_from_start(virt_stack *st, size_t k) { - assert(vstack_size(st) > k); - return st->buf[RUNTIME_VSTACK_SIZE - 1 - k]; +size_t vstack_kth_from_start (virt_stack *st, size_t k) { + assert(vstack_size(st) > k); + return st->buf[RUNTIME_VSTACK_SIZE - 1 - k]; } diff --git a/runtime/virt_stack.h b/runtime/virt_stack.h index 57291c4e4..7ea083e34 100644 --- a/runtime/virt_stack.h +++ b/runtime/virt_stack.h @@ -6,28 +6,28 @@ #define LAMA_RUNTIME_VIRT_STACK_H #define RUNTIME_VSTACK_SIZE 100000 -#include #include +#include struct { - size_t buf[RUNTIME_VSTACK_SIZE + 1]; - size_t cur; + size_t buf[RUNTIME_VSTACK_SIZE + 1]; + size_t cur; } typedef virt_stack; -virt_stack *vstack_create(); +virt_stack *vstack_create (); -void vstack_destruct(virt_stack *st); +void vstack_destruct (virt_stack *st); -void vstack_init(virt_stack *st); +void vstack_init (virt_stack *st); -void vstack_push(virt_stack *st, size_t value); +void vstack_push (virt_stack *st, size_t value); -size_t vstack_pop(virt_stack *st); +size_t vstack_pop (virt_stack *st); -void* vstack_top(virt_stack *st); +void *vstack_top (virt_stack *st); -size_t vstack_size(virt_stack *st); +size_t vstack_size (virt_stack *st); -size_t vstack_kth_from_start(virt_stack *st, size_t k); +size_t vstack_kth_from_start (virt_stack *st, size_t k); -#endif //LAMA_RUNTIME_VIRT_STACK_H +#endif //LAMA_RUNTIME_VIRT_STACK_H