mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 06:48:48 +00:00
add clang-format; reformat files
This commit is contained in:
parent
f20d351dd0
commit
ccd04c2159
10 changed files with 1885 additions and 1837 deletions
144
runtime/.clang-format
Normal file
144
runtime/.clang-format
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# Common settings
|
||||
BasedOnStyle: LLVM
|
||||
TabWidth: 2
|
||||
IndentWidth: 2
|
||||
UseTab: Never
|
||||
ColumnLimit: 100
|
||||
IndentCaseLabels: true
|
||||
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
---
|
||||
Language: Cpp
|
||||
|
||||
DisableFormat: false
|
||||
Standard: Cpp11
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
|
||||
|
||||
# Configure each individual brace in BraceWrapping
|
||||
BreakBeforeBraces: Attach
|
||||
# Control of individual brace wrapping cases
|
||||
BraceWrapping: {
|
||||
AfterClass: 'true'
|
||||
AfterControlStatement: 'true'
|
||||
AfterEnum : 'true'
|
||||
AfterFunction : 'true'
|
||||
AfterNamespace : 'true'
|
||||
AfterStruct : 'true'
|
||||
AfterUnion : 'true'
|
||||
BeforeCatch : 'true'
|
||||
BeforeElse : 'true'
|
||||
IndentBraces : 'false'
|
||||
AfterExternBlock : 'true'
|
||||
SplitEmptyFunction : 'false'
|
||||
SplitEmptyRecord : 'false'
|
||||
SplitEmptyNamespace : 'true'
|
||||
}
|
||||
|
||||
BreakAfterJavaFieldAnnotations: true
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakArrays: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakStringLiterals: true
|
||||
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
DerivePointerAlignment: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IndentCaseLabels: true
|
||||
FixNamespaceComments: true
|
||||
IndentWrappedFunctionNames: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
JavaScriptQuotes: Double
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions: {
|
||||
AfterControlStatements: 'true'
|
||||
AfterForeachMacros: 'true'
|
||||
AfterFunctionDeclarationName: 'true'
|
||||
AfterFunctionDefinitionName: 'true'
|
||||
AfterIfMacros: 'true'
|
||||
AfterOverloadedOperator: 'true'
|
||||
AfterRequiresInClause: 'true'
|
||||
AfterRequiresInExpression: 'true'
|
||||
BeforeNonEmptyParentheses: 'false'
|
||||
}
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceInEmptyBlock: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 3
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
|
||||
SortUsingDeclarations: true
|
||||
SortIncludes: CaseInsensitive
|
||||
|
||||
IndentGotoLabels: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: true
|
||||
|
||||
# Comments are for developers, they should arrange them
|
||||
ReflowComments: false
|
||||
|
||||
IncludeBlocks: Regroup
|
||||
IndentPPDirectives: AfterHash
|
||||
SeparateDefinitionBlocks: Always
|
||||
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 4
|
||||
Decimal: 0
|
||||
Hex: 0
|
||||
|
||||
---
|
||||
215
runtime/gc.c
215
runtime/gc.c
|
|
@ -1,18 +1,18 @@
|
|||
#define _GNU_SOURCE 1
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
#include "runtime_common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
static const size_t INIT_HEAP_SIZE = MINIMUM_HEAP_CAPACITY;
|
||||
|
||||
|
|
@ -91,18 +91,16 @@ void compact_phase(size_t additional_size) {
|
|||
size_t live_size = compute_locations();
|
||||
|
||||
// all in words
|
||||
size_t next_heap_size = MAX(live_size * EXTRA_ROOM_HEAP_COEFFICIENT + additional_size, MINIMUM_HEAP_CAPACITY);
|
||||
size_t next_heap_pseudo_size = MAX(next_heap_size, heap.size); // this is weird but here is why it happens:
|
||||
size_t next_heap_size =
|
||||
MAX(live_size * EXTRA_ROOM_HEAP_COEFFICIENT + additional_size, MINIMUM_HEAP_CAPACITY);
|
||||
size_t next_heap_pseudo_size =
|
||||
MAX(next_heap_size, heap.size); // this is weird but here is why it happens:
|
||||
// if we allocate too little heap right now, we may lose access to some alive objects
|
||||
// however, after we physically relocate all of our objects we will shrink allocated memory if it is possible
|
||||
|
||||
memory_chunk old_heap = heap;
|
||||
heap.begin = mremap(
|
||||
heap.begin,
|
||||
WORDS_TO_BYTES(heap.size),
|
||||
WORDS_TO_BYTES(next_heap_pseudo_size),
|
||||
MREMAP_MAYMOVE
|
||||
);
|
||||
heap.begin, WORDS_TO_BYTES(heap.size), WORDS_TO_BYTES(next_heap_pseudo_size), MREMAP_MAYMOVE);
|
||||
if (heap.begin == MAP_FAILED) {
|
||||
perror("ERROR: compact_phase: mremap failed\n");
|
||||
exit(1);
|
||||
|
|
@ -114,7 +112,8 @@ void compact_phase(size_t additional_size) {
|
|||
update_references(&old_heap);
|
||||
physically_relocate(&old_heap);
|
||||
|
||||
// shrink it if possible, otherwise this code won'test_small_tree_compaction do anything, in both cases references will remain valid
|
||||
// shrink it if possible, otherwise this code won'test_small_tree_compaction do anything, in both cases references
|
||||
// will remain valid
|
||||
heap.begin = mremap(
|
||||
heap.begin,
|
||||
WORDS_TO_BYTES(heap.size),
|
||||
|
|
@ -152,13 +151,13 @@ size_t compute_locations() {
|
|||
void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end) {
|
||||
for (size_t *ptr = (size_t *)start; ptr < (size_t *)end; ++ptr) {
|
||||
size_t ptr_value = *ptr;
|
||||
// this can't be expressed via is_valid_heap_pointer, because this pointer may point area corresponding to the old heap
|
||||
if (is_valid_pointer((size_t *) ptr_value)
|
||||
&& (size_t) old_heap->begin <= ptr_value
|
||||
&& ptr_value <= (size_t) old_heap->current
|
||||
) {
|
||||
// this can't be expressed via is_valid_heap_pointer, because this pointer may point area corresponding to the old
|
||||
// heap
|
||||
if (is_valid_pointer((size_t *)ptr_value) && (size_t)old_heap->begin <= ptr_value
|
||||
&& ptr_value <= (size_t)old_heap->current) {
|
||||
void *obj_ptr = (void *)heap.begin + ((void *)ptr_value - (void *)old_heap->begin);
|
||||
void *new_addr = (void*) heap.begin + ((void *) get_forward_address(obj_ptr) - (void *) old_heap->begin);
|
||||
void *new_addr =
|
||||
(void *)heap.begin + ((void *)get_forward_address(obj_ptr) - (void *)old_heap->begin);
|
||||
size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr));
|
||||
*(void **)ptr = new_addr + content_offset;
|
||||
}
|
||||
|
|
@ -169,29 +168,28 @@ void update_references(memory_chunk *old_heap) {
|
|||
heap_iterator it = heap_begin_iterator();
|
||||
while (!heap_is_done_iterator(&it)) {
|
||||
if (is_marked(get_object_content_ptr(it.current))) {
|
||||
for (
|
||||
obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
|
||||
for (obj_field_iterator field_iter = ptr_field_begin_iterator(it.current);
|
||||
!field_is_done_iterator(&field_iter);
|
||||
obj_next_ptr_field_iterator(&field_iter)
|
||||
) {
|
||||
|
||||
obj_next_ptr_field_iterator(&field_iter)) {
|
||||
|
||||
size_t *field_value = *(size_t **)field_iter.cur_field;
|
||||
if (field_value < old_heap->begin || field_value > old_heap->current) {
|
||||
continue;
|
||||
}
|
||||
if (field_value < old_heap->begin || field_value > old_heap->current) { continue; }
|
||||
// this pointer should also be modified according to old_heap->begin
|
||||
void *field_obj_content_addr = (void *) heap.begin + (*(void **) field_iter.cur_field - (void *) old_heap->begin);
|
||||
void *field_obj_content_addr =
|
||||
(void *)heap.begin + (*(void **)field_iter.cur_field - (void *)old_heap->begin);
|
||||
// important, we calculate new_addr very carefully here, because objects may relocate to another memory chunk
|
||||
void *new_addr =
|
||||
heap.begin + ((size_t *) get_forward_address(field_obj_content_addr) - (size_t *) old_heap->begin);
|
||||
heap.begin
|
||||
+ ((size_t *)get_forward_address(field_obj_content_addr) - (size_t *)old_heap->begin);
|
||||
// update field reference to point to new_addr
|
||||
// since, we want fields to point to an actual content, we need to add this extra content_offset
|
||||
// because forward_address itself is a pointer to the object's header
|
||||
size_t content_offset = get_header_size(get_type_row_ptr(field_obj_content_addr));
|
||||
#ifdef DEBUG_VERSION
|
||||
if (!is_valid_heap_pointer((void *)(new_addr + content_offset))) {
|
||||
fprintf(stderr, "ur: incorrect pointer assignment: on object with id %d", TO_DATA(get_object_content_ptr(it.current))->id);
|
||||
fprintf(stderr,
|
||||
"ur: incorrect pointer assignment: on object with id %d",
|
||||
TO_DATA(get_object_content_ptr(it.current))->id);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -204,7 +202,8 @@ void update_references(memory_chunk *old_heap) {
|
|||
scan_and_fix_region(old_heap, (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom);
|
||||
|
||||
// fix pointers from extra_roots
|
||||
scan_and_fix_region(old_heap, (void*) extra_roots.roots, (size_t*) extra_roots.roots + extra_roots.current_free);
|
||||
scan_and_fix_region(
|
||||
old_heap, (void *)extra_roots.roots, (size_t *)extra_roots.roots + extra_roots.current_free);
|
||||
|
||||
#ifndef DEBUG_VERSION
|
||||
// fix pointers from static area
|
||||
|
|
@ -234,9 +233,7 @@ bool is_valid_heap_pointer(const size_t *p) {
|
|||
return !UNBOXED(p) && (size_t)heap.begin <= (size_t)p && (size_t)p <= (size_t)heap.current;
|
||||
}
|
||||
|
||||
bool is_valid_pointer(const size_t *p) {
|
||||
return !UNBOXED(p);
|
||||
}
|
||||
bool is_valid_pointer (const size_t *p) { return !UNBOXED(p); }
|
||||
|
||||
static inline void queue_enqueue (heap_iterator *tail_iter, void *obj) {
|
||||
void *tail = tail_iter->current;
|
||||
|
|
@ -256,13 +253,7 @@ static inline void *queue_dequeue(heap_iterator *head_iter) {
|
|||
}
|
||||
|
||||
void mark (void *obj) {
|
||||
if (!is_valid_heap_pointer(obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_marked(obj)) {
|
||||
return;
|
||||
}
|
||||
if (!is_valid_heap_pointer(obj) || is_marked(obj)) { return; }
|
||||
|
||||
// TL;DR: [q_head_iter, q_tail_iter) q_head_iter -- current dequeue's victim, q_tail_iter -- place for next enqueue
|
||||
// in forward_address of corresponding element we store address of element to be removed after dequeue operation
|
||||
|
|
@ -271,19 +262,19 @@ void mark(void *obj) {
|
|||
heap_iterator q_tail_iter = q_head_iter;
|
||||
queue_enqueue(&q_tail_iter, obj);
|
||||
|
||||
// invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked object)
|
||||
// also each object is in queue only once
|
||||
while (q_head_iter.current != q_tail_iter.current) { // means the queue is not empty
|
||||
// invariant: queue contains only objects that are valid heap pointers (each corresponding to content of unmarked
|
||||
// object) also each object is in queue only once
|
||||
while (q_head_iter.current != q_tail_iter.current) {
|
||||
// while the queue is non-empty
|
||||
void *cur_obj = queue_dequeue(&q_head_iter);
|
||||
mark_object(cur_obj);
|
||||
void *header_ptr = get_obj_header_ptr(cur_obj, get_type_row_ptr(cur_obj));
|
||||
for (
|
||||
obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
|
||||
for (obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
|
||||
!field_is_done_iterator(&ptr_field_it);
|
||||
obj_next_ptr_field_iterator(&ptr_field_it)
|
||||
) {
|
||||
obj_next_ptr_field_iterator(&ptr_field_it)) {
|
||||
void *field_value = *(void **)ptr_field_it.cur_field;
|
||||
if (!is_valid_heap_pointer(field_value) || is_marked(field_value) || is_enqueued(field_value)) {
|
||||
if (!is_valid_heap_pointer(field_value) || is_marked(field_value)
|
||||
|| is_enqueued(field_value)) {
|
||||
continue;
|
||||
}
|
||||
// if we came to this point it must be true that field_value is unmarked and not currently in queue
|
||||
|
|
@ -309,9 +300,7 @@ void scan_global_area(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
extern void gc_test_and_mark_root(size_t **root) {
|
||||
mark((void *) *root);
|
||||
}
|
||||
extern void gc_test_and_mark_root (size_t **root) { mark((void *)*root); }
|
||||
|
||||
extern void __init (void) {
|
||||
signal(SIGSEGV, handler);
|
||||
|
|
@ -319,8 +308,8 @@ extern void __init(void) {
|
|||
|
||||
srandom(time(NULL));
|
||||
|
||||
heap.begin = mmap(NULL, space_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
|
||||
heap.begin = mmap(
|
||||
NULL, space_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
|
||||
if (heap.begin == MAP_FAILED) {
|
||||
perror("ERROR: __init: mmap failed\n");
|
||||
exit(1);
|
||||
|
|
@ -344,9 +333,7 @@ extern void __shutdown(void) {
|
|||
__gc_stack_bottom = 0;
|
||||
}
|
||||
|
||||
void clear_extra_roots(void) {
|
||||
extra_roots.current_free = 0;
|
||||
}
|
||||
void clear_extra_roots (void) { extra_roots.current_free = 0; }
|
||||
|
||||
void push_extra_root (void **p) {
|
||||
if (extra_roots.current_free >= MAX_EXTRA_ROOTS_NUMBER) {
|
||||
|
|
@ -376,11 +363,9 @@ void pop_extra_root(void **p) {
|
|||
size_t objects_snapshot (int *object_ids_buf, size_t object_ids_buf_size) {
|
||||
size_t *ids_ptr = (size_t *)object_ids_buf;
|
||||
size_t i = 0;
|
||||
for (
|
||||
heap_iterator it = heap_begin_iterator();
|
||||
for (heap_iterator it = heap_begin_iterator();
|
||||
!heap_is_done_iterator(&it) && i < object_ids_buf_size;
|
||||
heap_next_obj_iterator(&it), ++i
|
||||
) {
|
||||
heap_next_obj_iterator(&it), ++i) {
|
||||
void *header_ptr = it.current;
|
||||
data *d = TO_DATA(get_object_content_ptr(header_ptr));
|
||||
ids_ptr[i] = d->id;
|
||||
|
|
@ -392,25 +377,16 @@ extern char* de_hash (int);
|
|||
|
||||
void dump_heap () {
|
||||
size_t i = 0;
|
||||
for (
|
||||
heap_iterator it = heap_begin_iterator();
|
||||
!heap_is_done_iterator(&it);
|
||||
heap_next_obj_iterator(&it), ++i
|
||||
) {
|
||||
for (heap_iterator it = heap_begin_iterator(); !heap_is_done_iterator(&it);
|
||||
heap_next_obj_iterator(&it), ++i) {
|
||||
void *header_ptr = it.current;
|
||||
void *content_ptr = get_object_content_ptr(header_ptr);
|
||||
data *d = TO_DATA(content_ptr);
|
||||
lama_type t = get_type_header_ptr(header_ptr);
|
||||
switch (t) {
|
||||
case ARRAY:
|
||||
fprintf(stderr, "of kind ARRAY\n");
|
||||
break;
|
||||
case CLOSURE:
|
||||
fprintf(stderr, "of kind CLOSURE\n");
|
||||
break;
|
||||
case STRING:
|
||||
fprintf(stderr, "of kind STRING\n");
|
||||
break;
|
||||
case ARRAY: fprintf(stderr, "of kind ARRAY\n"); break;
|
||||
case CLOSURE: fprintf(stderr, "of kind CLOSURE\n"); break;
|
||||
case STRING: fprintf(stderr, "of kind STRING\n"); break;
|
||||
case SEXP:
|
||||
fprintf(stderr, "of kind SEXP with tag %s\n", de_hash(TO_SEXP(content_ptr)->tag));
|
||||
break;
|
||||
|
|
@ -430,7 +406,6 @@ void set_extra_roots(size_t extra_roots_size, void **extra_roots_ptr) {
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
size_t get_forward_address (void *obj) {
|
||||
|
|
@ -487,9 +462,7 @@ void heap_next_obj_iterator(heap_iterator *it) {
|
|||
it->current += obj_size;
|
||||
}
|
||||
|
||||
bool heap_is_done_iterator(heap_iterator *it) {
|
||||
return it->current >= heap.current;
|
||||
}
|
||||
bool heap_is_done_iterator (heap_iterator *it) { return it->current >= heap.current; }
|
||||
|
||||
lama_type get_type_row_ptr (void *ptr) {
|
||||
data *data_ptr = TO_DATA(ptr);
|
||||
|
|
@ -499,21 +472,20 @@ lama_type get_type_row_ptr(void *ptr) {
|
|||
lama_type get_type_header_ptr (void *ptr) {
|
||||
int *header = (int *)ptr;
|
||||
switch (TAG(*header)) {
|
||||
case ARRAY_TAG:
|
||||
return ARRAY;
|
||||
case STRING_TAG:
|
||||
return STRING;
|
||||
case CLOSURE_TAG:
|
||||
return CLOSURE;
|
||||
case SEXP_TAG:
|
||||
return SEXP;
|
||||
case ARRAY_TAG: return ARRAY;
|
||||
case STRING_TAG: return STRING;
|
||||
case CLOSURE_TAG: return CLOSURE;
|
||||
case SEXP_TAG: return SEXP;
|
||||
default: {
|
||||
#ifdef DEBUG_VERSION
|
||||
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, cur_id=%d", cur_id);
|
||||
raise(SIGINT); // only for debug purposes
|
||||
#else
|
||||
|
||||
fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, ptr is %p, heap size is %d\n", ptr, heap.size);
|
||||
fprintf(stderr,
|
||||
"ERROR: get_type_header_ptr: unknown object header, ptr is %p, "
|
||||
"heap size is %d\n",
|
||||
ptr,
|
||||
heap.size);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -528,20 +500,15 @@ size_t obj_size_row_ptr(void *ptr) {
|
|||
size_t obj_size_header_ptr (void *ptr) {
|
||||
int len = LEN(*(int *)ptr);
|
||||
switch (get_type_header_ptr(ptr)) {
|
||||
case ARRAY:
|
||||
return array_size(len);
|
||||
case STRING:
|
||||
return string_size(len);
|
||||
case CLOSURE:
|
||||
return closure_size(len);
|
||||
case SEXP:
|
||||
return sexp_size(len);
|
||||
case ARRAY: return array_size(len);
|
||||
case STRING: return string_size(len);
|
||||
case CLOSURE: return closure_size(len);
|
||||
case SEXP: return sexp_size(len);
|
||||
default: {
|
||||
#ifdef DEBUG_VERSION
|
||||
fprintf(stderr, "ERROR: obj_size_header_ptr: unknown object header, cur_id=%d", cur_id);
|
||||
raise(SIGINT); // only for debug purposes
|
||||
#else
|
||||
|
||||
perror("ERROR: obj_size_header_ptr: unknown object header");
|
||||
#endif
|
||||
exit(1);
|
||||
|
|
@ -549,54 +516,37 @@ size_t obj_size_header_ptr(void *ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t array_size(size_t sz) {
|
||||
return get_header_size(ARRAY) + MEMBER_SIZE * sz;
|
||||
}
|
||||
size_t array_size (size_t sz) { return get_header_size(ARRAY) + MEMBER_SIZE * sz; }
|
||||
|
||||
size_t string_size (size_t len) {
|
||||
// string should be null terminated
|
||||
return get_header_size(STRING) + len + 1;
|
||||
}
|
||||
|
||||
size_t closure_size(size_t sz) {
|
||||
return get_header_size(CLOSURE) + MEMBER_SIZE * sz;
|
||||
}
|
||||
|
||||
size_t sexp_size(size_t members) {
|
||||
return get_header_size(SEXP) + MEMBER_SIZE * members;
|
||||
}
|
||||
size_t closure_size (size_t sz) { return get_header_size(CLOSURE) + MEMBER_SIZE * sz; }
|
||||
|
||||
size_t sexp_size (size_t members) { return get_header_size(SEXP) + MEMBER_SIZE * members; }
|
||||
|
||||
obj_field_iterator field_begin_iterator (void *obj) {
|
||||
lama_type type = get_type_header_ptr(obj);
|
||||
obj_field_iterator it = {.type = type, .obj_ptr = obj, .cur_field = get_object_content_ptr(obj)};
|
||||
// since string doesn't have any actual fields we set cur_field to the end of object
|
||||
if (type == STRING) {
|
||||
it.cur_field = get_end_of_obj(it.obj_ptr);
|
||||
}
|
||||
if (type == STRING) { it.cur_field = get_end_of_obj(it.obj_ptr); }
|
||||
// skip first member which is basically pointer to the code
|
||||
if (type == CLOSURE) {
|
||||
it.cur_field += MEMBER_SIZE;
|
||||
}
|
||||
if (type == CLOSURE) { it.cur_field += MEMBER_SIZE; }
|
||||
return it;
|
||||
}
|
||||
|
||||
obj_field_iterator ptr_field_begin_iterator (void *obj) {
|
||||
obj_field_iterator it = field_begin_iterator(obj);
|
||||
// corner case when obj has no fields
|
||||
if (field_is_done_iterator(&it)) {
|
||||
return it;
|
||||
}
|
||||
if (is_valid_pointer(*(size_t **) it.cur_field)) {
|
||||
return it;
|
||||
}
|
||||
if (field_is_done_iterator(&it)) { return it; }
|
||||
if (is_valid_pointer(*(size_t **)it.cur_field)) { return it; }
|
||||
obj_next_ptr_field_iterator(&it);
|
||||
return it;
|
||||
}
|
||||
|
||||
void obj_next_field_iterator(obj_field_iterator *it) {
|
||||
it->cur_field += MEMBER_SIZE;
|
||||
}
|
||||
void obj_next_field_iterator (obj_field_iterator *it) { it->cur_field += MEMBER_SIZE; }
|
||||
|
||||
void obj_next_ptr_field_iterator (obj_field_iterator *it) {
|
||||
do {
|
||||
|
|
@ -608,29 +558,22 @@ bool field_is_done_iterator(obj_field_iterator *it) {
|
|||
return it->cur_field >= get_end_of_obj(it->obj_ptr);
|
||||
}
|
||||
|
||||
void *get_obj_header_ptr(void *ptr, lama_type type) {
|
||||
return ptr - get_header_size(type);
|
||||
}
|
||||
void *get_obj_header_ptr (void *ptr, lama_type type) { return ptr - get_header_size(type); }
|
||||
|
||||
void *get_object_content_ptr (void *header_ptr) {
|
||||
lama_type type = get_type_header_ptr(header_ptr);
|
||||
return header_ptr + get_header_size(type);
|
||||
}
|
||||
|
||||
void *get_end_of_obj(void *header_ptr) {
|
||||
return header_ptr + obj_size_header_ptr(header_ptr);
|
||||
}
|
||||
void *get_end_of_obj (void *header_ptr) { return header_ptr + obj_size_header_ptr(header_ptr); }
|
||||
|
||||
size_t get_header_size (lama_type type) {
|
||||
switch (type) {
|
||||
case STRING:
|
||||
case CLOSURE:
|
||||
case ARRAY:
|
||||
return DATA_HEADER_SZ;
|
||||
case SEXP:
|
||||
return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
|
||||
default:
|
||||
perror("ERROR: get_header_size: unknown object type");
|
||||
case ARRAY: return DATA_HEADER_SZ;
|
||||
case SEXP: return SEXP_ONLY_HEADER_SZ + DATA_HEADER_SZ;
|
||||
default: perror("ERROR: get_header_size: unknown object type");
|
||||
#ifdef DEBUG_VERSION
|
||||
raise(SIGINT); // only for debug purposes
|
||||
#endif
|
||||
|
|
|
|||
25
runtime/gc.h
25
runtime/gc.h
|
|
@ -9,8 +9,11 @@
|
|||
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
|
||||
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
|
||||
#define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1)))
|
||||
# define GET_FORWARD_ADDRESS(x) (((size_t) (x)) & (~3)) // since last 2 bits are used for mark-bit and enqueued-bit and due to correct alignment we can expect that last 2 bits don't influence address (they should always be zero)
|
||||
# define SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((int) (addr)))) // take the last two bits as they are and make all others zero
|
||||
#define GET_FORWARD_ADDRESS(x) \
|
||||
(((size_t)(x)) \
|
||||
& (~3)) // since last 2 bits are used for mark-bit and enqueued-bit and due to correct alignment we can expect that last 2 bits don't influence address (they should always be zero)
|
||||
#define SET_FORWARD_ADDRESS(x, addr) \
|
||||
(x = ((x & 3) | ((int)(addr)))) // take the last two bits as they are and make all others zero
|
||||
#define EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter
|
||||
#ifdef DEBUG_VERSION
|
||||
# define MINIMUM_HEAP_CAPACITY (8)
|
||||
|
|
@ -18,9 +21,8 @@
|
|||
# define MINIMUM_HEAP_CAPACITY (1 << 10)
|
||||
#endif
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum { ARRAY, CLOSURE, STRING, SEXP } lama_type;
|
||||
|
||||
|
|
@ -45,6 +47,7 @@ typedef struct {
|
|||
|
||||
/* GC extra roots */
|
||||
#define MAX_EXTRA_ROOTS_NUMBER 32
|
||||
|
||||
typedef struct {
|
||||
int current_free;
|
||||
void **roots[MAX_EXTRA_ROOTS_NUMBER];
|
||||
|
|
@ -62,7 +65,8 @@ void *gc_alloc_on_existing_heap(size_t);
|
|||
void mark (void *obj);
|
||||
void mark_phase (void);
|
||||
// written in ASM, scans stack for pointers to the heap and starts marking process
|
||||
extern void __gc_root_scan_stack(void); // TODO: write without ASM, since it is absolutely not necessary
|
||||
extern void
|
||||
__gc_root_scan_stack (void); // TODO: write without ASM, since it is absolutely not necessary
|
||||
// marks each pointer from extra roots
|
||||
void scan_extra_roots (void);
|
||||
#ifndef DEBUG_VERSION
|
||||
|
|
@ -77,9 +81,12 @@ void update_references(memory_chunk *);
|
|||
void physically_relocate (memory_chunk *);
|
||||
|
||||
// written in ASM
|
||||
extern void __gc_init (void); // MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we are working with virtual stack as happens in tests)
|
||||
extern void __init (void); // should be called before interaction with GC in case of using in tests with virtual stack, otherwise it is automatically invoked by __gc_init
|
||||
extern void __shutdown (void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC
|
||||
extern void __gc_init (
|
||||
void); // MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we are working with virtual stack as happens in tests)
|
||||
extern void __init (
|
||||
void); // should be called before interaction with GC in case of using in tests with virtual stack, otherwise it is automatically invoked by __gc_init
|
||||
extern void __shutdown (
|
||||
void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC
|
||||
// written in ASM
|
||||
extern void __pre_gc (void);
|
||||
// written in ASM
|
||||
|
|
@ -96,7 +103,6 @@ void push_extra_root (void ** p);
|
|||
|
||||
void pop_extra_root (void **p);
|
||||
|
||||
|
||||
/* Functions for tests */
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
|
|
@ -115,7 +121,6 @@ void set_extra_roots(size_t extra_roots_size, void** extra_roots_ptr);
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
// accepts pointer to the start of the region and to the end of the region
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
.data
|
||||
printf_format: .string "Stack root: %lx\n"
|
||||
printf_format2: .string "BOT: %lx\n"
|
||||
printf_format3: .string "TOP: %lx\n"
|
||||
printf_format4: .string "EAX: %lx\n"
|
||||
printf_format5: .string "LOL\n"
|
||||
__gc_stack_bottom: .long 0
|
||||
__gc_stack_top: .long 0
|
||||
|
||||
|
|
@ -13,8 +8,9 @@ __gc_stack_top: .long 0
|
|||
.globl __gc_root_scan_stack
|
||||
.globl __gc_stack_top
|
||||
.globl __gc_stack_bottom
|
||||
.extern init_pool
|
||||
.extern gc_test_and_copy_root
|
||||
.extern __init
|
||||
.extern gc_test_and_mark_root
|
||||
|
||||
.text
|
||||
|
||||
__gc_init:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
#define _GNU_SOURCE 1
|
||||
|
||||
#include "runtime.h"
|
||||
# include "runtime_common.h"
|
||||
|
||||
#include "gc.h"
|
||||
#include "runtime_common.h"
|
||||
|
||||
#define __ENABLE_GC__
|
||||
#ifndef __ENABLE_GC__
|
||||
|
|
@ -25,6 +26,7 @@ extern void __post_gc ();
|
|||
# define __post_gc __post_gc_subst
|
||||
|
||||
void __pre_gc_subst () { }
|
||||
|
||||
void __post_gc_subst () { }
|
||||
|
||||
#endif
|
||||
|
|
@ -53,12 +55,18 @@ void Lassert (void *f, char *s, ...) {
|
|||
}
|
||||
|
||||
#define ASSERT_BOXED(memo, x) \
|
||||
do if (UNBOXED(x)) failure ("boxed value expected in %s\n", memo); while (0)
|
||||
do \
|
||||
if (UNBOXED(x)) failure("boxed value expected in %s\n", memo); \
|
||||
while (0)
|
||||
#define ASSERT_UNBOXED(memo, x) \
|
||||
do if (!UNBOXED(x)) failure ("unboxed value expected in %s\n", memo); while (0)
|
||||
do \
|
||||
if (!UNBOXED(x)) failure("unboxed value expected in %s\n", memo); \
|
||||
while (0)
|
||||
#define ASSERT_STRING(memo, x) \
|
||||
do if (!UNBOXED(x) && TAG(TO_DATA(x)->data_header) \
|
||||
!= STRING_TAG) failure ("string value expected in %s\n", memo); while (0)
|
||||
do \
|
||||
if (!UNBOXED(x) && TAG(TO_DATA(x)->data_header) != STRING_TAG) \
|
||||
failure("string value expected in %s\n", memo); \
|
||||
while (0)
|
||||
|
||||
//extern void* alloc (size_t);
|
||||
extern void *Bsexp (int n, ...);
|
||||
|
|
@ -90,8 +98,8 @@ extern int LcompareTags (void *p, void *q) {
|
|||
#else
|
||||
BOX((GET_SEXP_TAG(TO_SEXP(p)->data_header)) - (GET_SEXP_TAG(TO_SEXP(p)->data_header)));
|
||||
#endif
|
||||
}
|
||||
else failure ("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
|
||||
} else
|
||||
failure("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
|
||||
|
||||
return 0; // never happens
|
||||
}
|
||||
|
|
@ -130,9 +138,7 @@ int Ls__Infix_3838 (void *p, void *q) {
|
|||
}
|
||||
|
||||
// Functional synonym for built-in operator "==";
|
||||
int Ls__Infix_6161 (void *p, void *q) {
|
||||
return BOX(p == q);
|
||||
}
|
||||
int Ls__Infix_6161 (void *p, void *q) { return BOX(p == q); }
|
||||
|
||||
// Functional synonym for built-in operator "!=";
|
||||
int Ls__Infix_3361 (void *p, void *q) {
|
||||
|
|
@ -236,7 +242,8 @@ extern int LtagHash (char *s) {
|
|||
char *q = chars;
|
||||
int pos = 0;
|
||||
|
||||
for (; *q && *q != *p; q++, pos++);
|
||||
for (; *q && *q != *p; q++, pos++)
|
||||
;
|
||||
|
||||
if (*q) h = (h << 6) | pos;
|
||||
else failure("tagHash: character not found: %c\n", *p);
|
||||
|
|
@ -244,9 +251,7 @@ extern int LtagHash (char *s) {
|
|||
p++;
|
||||
}
|
||||
|
||||
if (strcmp (s, de_hash (h)) != 0) {
|
||||
failure ("%s <-> %s\n", s, de_hash(h));
|
||||
}
|
||||
if (strcmp(s, de_hash(h)) != 0) { failure("%s <-> %s\n", s, de_hash(h)); }
|
||||
|
||||
return BOX(h);
|
||||
}
|
||||
|
|
@ -258,8 +263,10 @@ char* de_hash (int n) {
|
|||
p = &buf[5];
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
printf ("de_hash: data_header: %d\n", n); fflush (stdout);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("de_hash: data_header: %d\n", n);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
*p-- = 0;
|
||||
|
|
@ -267,7 +274,8 @@ char* de_hash (int n) {
|
|||
while (n != 0) {
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("char: %c\n", chars [n & 0x003F]); fflush (stdout);
|
||||
printf("char: %c\n", chars[n & 0x003F]);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
*p-- = chars[n & 0x003F];
|
||||
n = n >> 6;
|
||||
|
|
@ -297,9 +305,7 @@ static void createStringBuf () {
|
|||
stringBuf.len = STRINGBUF_INIT;
|
||||
}
|
||||
|
||||
static void deleteStringBuf () {
|
||||
free (stringBuf.contents);
|
||||
}
|
||||
static void deleteStringBuf () { free(stringBuf.contents); }
|
||||
|
||||
static void extendStringBuf () {
|
||||
int len = stringBuf.len << 1;
|
||||
|
|
@ -309,8 +315,7 @@ static void extendStringBuf () {
|
|||
}
|
||||
|
||||
static void vprintStringBuf (char *fmt, va_list args) {
|
||||
int written = 0,
|
||||
rest = 0;
|
||||
int written = 0, rest = 0;
|
||||
char *buf = (char *)BOX(NULL);
|
||||
va_list vsnargs;
|
||||
|
||||
|
|
@ -353,9 +358,7 @@ static void printValue (void *p) {
|
|||
a = TO_DATA(p);
|
||||
|
||||
switch (TAG(a->data_header)) {
|
||||
case STRING_TAG:
|
||||
printStringBuf ("\"%s\"", a->contents);
|
||||
break;
|
||||
case STRING_TAG: printStringBuf("\"%s\"", a->contents); break;
|
||||
|
||||
case CLOSURE_TAG:
|
||||
printStringBuf("<closure ");
|
||||
|
|
@ -387,12 +390,10 @@ static void printValue (void *p) {
|
|||
if (!UNBOXED(b)) {
|
||||
printStringBuf(", ");
|
||||
b = TO_DATA(b);
|
||||
}
|
||||
else break;
|
||||
} else break;
|
||||
}
|
||||
printStringBuf("}");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printStringBuf("%s", tag);
|
||||
if (LEN(a->data_header)) {
|
||||
printStringBuf(" (");
|
||||
|
|
@ -403,11 +404,9 @@ static void printValue (void *p) {
|
|||
printStringBuf(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
printStringBuf ("*** invalid data_header: 0x%x ***", TAG(a->data_header));
|
||||
default: printStringBuf("*** invalid data_header: 0x%x ***", TAG(a->data_header));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -416,14 +415,13 @@ static void stringcat (void *p) {
|
|||
data *a;
|
||||
int i;
|
||||
|
||||
if (UNBOXED(p)) ;
|
||||
if (UNBOXED(p))
|
||||
;
|
||||
else {
|
||||
a = TO_DATA(p);
|
||||
|
||||
switch (TAG(a->data_header)) {
|
||||
case STRING_TAG:
|
||||
printStringBuf ("%s", a->contents);
|
||||
break;
|
||||
case STRING_TAG: printStringBuf("%s", a->contents); break;
|
||||
|
||||
case SEXP_TAG: {
|
||||
char *tag = de_hash(TO_SEXP(p)->tag);
|
||||
|
|
@ -436,16 +434,12 @@ static void stringcat (void *p) {
|
|||
b = (data *)((int *)b->contents)[1];
|
||||
if (!UNBOXED(b)) {
|
||||
b = TO_DATA(b);
|
||||
} else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
else printStringBuf ("*** non-list data_header: %s ***", tag);
|
||||
}
|
||||
break;
|
||||
} else printStringBuf("*** non-list data_header: %s ***", tag);
|
||||
} break;
|
||||
|
||||
default:
|
||||
printStringBuf ("*** invalid data_header: 0x%x ***", TAG(a->data_header));
|
||||
default: printStringBuf("*** invalid data_header: 0x%x ***", TAG(a->data_header));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -470,8 +464,7 @@ extern int LmatchSubString (char *subj, char *patt, int pos) {
|
|||
|
||||
n = LEN(p->data_header);
|
||||
|
||||
if (n + UNBOX(pos) > LEN(s->data_header))
|
||||
return BOX(0);
|
||||
if (n + UNBOX(pos) > LEN(s->data_header)) return BOX(0);
|
||||
|
||||
return BOX(strncmp(subj + UNBOX(pos), patt, n) == 0);
|
||||
}
|
||||
|
|
@ -501,7 +494,10 @@ extern void* Lsubstring (void *subj, int p, int l) {
|
|||
}
|
||||
|
||||
failure("substring: index out of bounds (position=%d, length=%d, \
|
||||
subject length=%d)", pp, ll, LEN(d->data_header));
|
||||
subject length=%d)",
|
||||
pp,
|
||||
ll,
|
||||
LEN(d->data_header));
|
||||
}
|
||||
|
||||
extern struct re_pattern_buffer *Lregexp (char *regexp) {
|
||||
|
|
@ -513,9 +509,7 @@ extern struct re_pattern_buffer *Lregexp (char *regexp) {
|
|||
|
||||
int n = (int)re_compile_pattern(regexp, strlen(regexp), b);
|
||||
|
||||
if (n != 0) {
|
||||
failure ("%", strerror (n));
|
||||
};
|
||||
if (n != 0) { failure("%", strerror(n)); };
|
||||
|
||||
return b;
|
||||
}
|
||||
|
|
@ -531,9 +525,7 @@ extern int LregexpMatch (struct re_pattern_buffer *b, char *s, int pos) {
|
|||
|
||||
/* printf ("regexpMatch %x: %s, res=%d\n", b, s+UNBOX(pos), res); */
|
||||
|
||||
if (res) {
|
||||
return BOX (res);
|
||||
}
|
||||
if (res) { return BOX(res); }
|
||||
|
||||
return BOX(res);
|
||||
}
|
||||
|
|
@ -547,8 +539,10 @@ void *Lclone (void *p) {
|
|||
int n;
|
||||
#ifdef DEBUG_PRINT
|
||||
register int *ebp asm("ebp");
|
||||
indent++; print_indent ();
|
||||
printf ("Lclone arg: %p %p\n", &p, p); fflush (stdout);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("Lclone arg: %p %p\n", &p, p);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
__pre_gc();
|
||||
|
||||
|
|
@ -562,19 +556,22 @@ void *Lclone (void *p) {
|
|||
case STRING_TAG:
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Lclone: string1 &p=%p p=%p\n", &p, p); fflush (stdout);
|
||||
printf("Lclone: string1 &p=%p p=%p\n", &p, p);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
res = Bstring(TO_DATA(p)->contents);
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Lclone: string2 %p %p\n", &p, p); fflush (stdout);
|
||||
printf("Lclone: string2 %p %p\n", &p, p);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ARRAY_TAG:
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Lclone: array &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout);
|
||||
printf("Lclone: array &p=%p p=%p ebp=%p\n", &p, p, ebp);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
obj = (data *)alloc_array(l);
|
||||
memcpy(obj, TO_DATA(p), array_size(l));
|
||||
|
|
@ -583,7 +580,8 @@ void *Lclone (void *p) {
|
|||
case CLOSURE_TAG:
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Lclone: closure &p=%p p=%p ebp=%p\n", &p, p, ebp); fflush (stdout);
|
||||
printf("Lclone: closure &p=%p p=%p ebp=%p\n", &p, p, ebp);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
obj = (data *)alloc_closure(l);
|
||||
memcpy(obj, TO_DATA(p), closure_size(l));
|
||||
|
|
@ -592,33 +590,38 @@ void *Lclone (void *p) {
|
|||
|
||||
case SEXP_TAG:
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent (); printf ("Lclone: sexp\n"); fflush (stdout);
|
||||
print_indent();
|
||||
printf("Lclone: sexp\n");
|
||||
fflush(stdout);
|
||||
#endif
|
||||
sobj = (sexp *)alloc_sexp(l);
|
||||
memcpy(sobj, TO_SEXP(p), sexp_size(l));
|
||||
res = (void *)sobj->contents.contents;
|
||||
break;
|
||||
|
||||
default:
|
||||
failure ("invalid data_header %d in clone *****\n", t);
|
||||
default: failure("invalid data_header %d in clone *****\n", t);
|
||||
}
|
||||
pop_extra_root(&p);
|
||||
}
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent (); printf ("Lclone ends1\n"); fflush (stdout);
|
||||
print_indent();
|
||||
printf("Lclone ends1\n");
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
__post_gc();
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Lclone ends2\n"); fflush (stdout);
|
||||
printf("Lclone ends2\n");
|
||||
fflush(stdout);
|
||||
indent--;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#define HASH_DEPTH 3
|
||||
# define HASH_APPEND(acc, x) (((acc + (unsigned) x) << (WORD_SIZE / 2)) | ((acc + (unsigned) x) >> (WORD_SIZE / 2)))
|
||||
#define HASH_APPEND(acc, x) \
|
||||
(((acc + (unsigned)x) << (WORD_SIZE / 2)) | ((acc + (unsigned)x) >> (WORD_SIZE / 2)))
|
||||
|
||||
int inner_hash (int depth, unsigned acc, void *p) {
|
||||
if (depth > HASH_DEPTH) return acc;
|
||||
|
|
@ -648,9 +651,7 @@ int inner_hash (int depth, unsigned acc, void *p) {
|
|||
i = 1;
|
||||
break;
|
||||
|
||||
case ARRAY_TAG:
|
||||
i = 0;
|
||||
break;
|
||||
case ARRAY_TAG: i = 0; break;
|
||||
|
||||
case SEXP_TAG: {
|
||||
#ifndef DEBUG_PRINT
|
||||
|
|
@ -663,16 +664,13 @@ int inner_hash (int depth, unsigned acc, void *p) {
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
failure ("invalid data_header %d in hash *****\n", t);
|
||||
default: failure("invalid data_header %d in hash *****\n", t);
|
||||
}
|
||||
|
||||
for (; i<l; i++)
|
||||
acc = inner_hash (depth+1, acc, ((void**) a->contents)[i]);
|
||||
for (; i < l; i++) acc = inner_hash(depth + 1, acc, ((void **)a->contents)[i]);
|
||||
|
||||
return acc;
|
||||
}
|
||||
else return HASH_APPEND(acc, p);
|
||||
} else return HASH_APPEND(acc, p);
|
||||
}
|
||||
|
||||
extern void *LstringInt (char *b) {
|
||||
|
|
@ -681,34 +679,30 @@ extern void* LstringInt (char *b) {
|
|||
return (void *)BOX(n);
|
||||
}
|
||||
|
||||
extern int Lhash (void *p) {
|
||||
return BOX(0x3fffff & inner_hash (0, 0, p));
|
||||
}
|
||||
extern int Lhash (void *p) { return BOX(0x3fffff & inner_hash(0, 0, p)); }
|
||||
|
||||
extern int LflatCompare (void *p, void *q) {
|
||||
if (UNBOXED(p)) {
|
||||
if (UNBOXED(q)) {
|
||||
return BOX (UNBOX(p) - UNBOX(q));
|
||||
}
|
||||
if (UNBOXED(q)) { return BOX(UNBOX(p) - UNBOX(q)); }
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (~UNBOXED(q)) {
|
||||
} else if (~UNBOXED(q)) {
|
||||
return BOX(p - q);
|
||||
}
|
||||
else BOX(1);
|
||||
} else BOX(1);
|
||||
}
|
||||
|
||||
extern int Lcompare (void *p, void *q) {
|
||||
# define COMPARE_AND_RETURN(x,y) do if (x != y) return BOX(x - y); while (0)
|
||||
#define COMPARE_AND_RETURN(x, y) \
|
||||
do \
|
||||
if (x != y) return BOX(x - y); \
|
||||
while (0)
|
||||
|
||||
if (p == q) return BOX(0);
|
||||
|
||||
if (UNBOXED(p)) {
|
||||
if (UNBOXED(q)) return BOX(UNBOX(p) - UNBOX(q));
|
||||
else return BOX(-1);
|
||||
}
|
||||
else if (UNBOXED(q)) return BOX(1);
|
||||
} else if (UNBOXED(q)) return BOX(1);
|
||||
else {
|
||||
if (is_valid_heap_pointer(p)) {
|
||||
if (is_valid_heap_pointer(q)) {
|
||||
|
|
@ -720,8 +714,7 @@ extern int Lcompare (void *p, void *q) {
|
|||
COMPARE_AND_RETURN(ta, tb);
|
||||
|
||||
switch (ta) {
|
||||
case STRING_TAG:
|
||||
return BOX(strcmp (a->contents, b->contents));
|
||||
case STRING_TAG: return BOX(strcmp(a->contents, b->contents));
|
||||
|
||||
case CLOSURE_TAG:
|
||||
COMPARE_AND_RETURN(((void **)a->contents)[0], ((void **)b->contents)[0]);
|
||||
|
|
@ -738,7 +731,8 @@ extern int Lcompare (void *p, void *q) {
|
|||
#ifndef DEBUG_PRINT
|
||||
int ta = TO_SEXP(p)->tag, tb = TO_SEXP(q)->tag;
|
||||
#else
|
||||
int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header), tb = GET_SEXP_TAG(TO_SEXP(q)->data_header);
|
||||
int ta = GET_SEXP_TAG(TO_SEXP(p)->data_header),
|
||||
tb = GET_SEXP_TAG(TO_SEXP(q)->data_header);
|
||||
#endif
|
||||
COMPARE_AND_RETURN(ta, tb);
|
||||
COMPARE_AND_RETURN(la, lb);
|
||||
|
|
@ -746,8 +740,7 @@ extern int Lcompare (void *p, void *q) {
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
failure ("invalid data_header %d in compare *****\n", ta);
|
||||
default: failure("invalid data_header %d in compare *****\n", ta);
|
||||
}
|
||||
|
||||
for (; i < la; i++) {
|
||||
|
|
@ -756,10 +749,8 @@ extern int Lcompare (void *p, void *q) {
|
|||
}
|
||||
|
||||
return BOX(0);
|
||||
}
|
||||
else return BOX(-1);
|
||||
}
|
||||
else if (is_valid_heap_pointer (q)) return BOX(1);
|
||||
} else return BOX(-1);
|
||||
} else if (is_valid_heap_pointer(q)) return BOX(1);
|
||||
else return BOX(p - q);
|
||||
}
|
||||
}
|
||||
|
|
@ -773,9 +764,7 @@ extern void* Belem (void *p, int i) {
|
|||
a = TO_DATA(p);
|
||||
i = UNBOX(i);
|
||||
|
||||
if (TAG(a->data_header) == STRING_TAG) {
|
||||
return (void*) BOX(a->contents[i]);
|
||||
}
|
||||
if (TAG(a->data_header) == STRING_TAG) { return (void *)BOX(a->contents[i]); }
|
||||
|
||||
return (void *)((int *)a->contents)[i];
|
||||
}
|
||||
|
|
@ -820,7 +809,8 @@ extern void* Bstring (void *p) {
|
|||
|
||||
__pre_gc();
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("Bstring: call LmakeString %s %p %p %p %i\n", p, &p, p, s, n);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
|
@ -829,12 +819,14 @@ extern void* Bstring (void *p) {
|
|||
pop_extra_root(&p);
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("\tBstring: call strncpy: %p %p %p %i\n", &p, p, s, n); fflush(stdout);
|
||||
printf("\tBstring: call strncpy: %p %p %p %i\n", &p, p, s, n);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
strncpy((char *)&TO_DATA(s)->contents, p, n + 1); // +1 because of '\0' in the end of C-strings
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("\tBstring: ends\n"); fflush(stdout);
|
||||
printf("\tBstring: ends\n");
|
||||
fflush(stdout);
|
||||
indent--;
|
||||
#endif
|
||||
__post_gc();
|
||||
|
|
@ -892,13 +884,13 @@ extern void* Bclosure (int bn, void *entry, ...) {
|
|||
|
||||
__pre_gc();
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
printf ("Bclosure: create n = %d\n", n); fflush(stdout);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("Bclosure: create n = %d\n", n);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
argss = (ebp + 12);
|
||||
for (i = 0; i<n; i++, argss++) {
|
||||
push_extra_root ((void**)argss);
|
||||
}
|
||||
for (i = 0; i < n; i++, argss++) { push_extra_root((void **)argss); }
|
||||
|
||||
r = (data *)alloc_closure(n + 1);
|
||||
|
||||
|
|
@ -916,13 +908,12 @@ extern void* Bclosure (int bn, void *entry, ...) {
|
|||
__post_gc();
|
||||
|
||||
argss--;
|
||||
for (i = 0; i<n; i++, argss--) {
|
||||
pop_extra_root ((void**)argss);
|
||||
}
|
||||
for (i = 0; i < n; i++, argss--) { pop_extra_root((void **)argss); }
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("Bclosure: ends\n", n); fflush(stdout);
|
||||
printf("Bclosure: ends\n", n);
|
||||
fflush(stdout);
|
||||
indent--;
|
||||
#endif
|
||||
|
||||
|
|
@ -938,8 +929,10 @@ extern void* Barray (int bn, ...) {
|
|||
__pre_gc();
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
printf ("Barray: create n = %d\n", n); fflush(stdout);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("Barray: create n = %d\n", n);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
r = (data *)alloc_array(n);
|
||||
|
||||
|
|
@ -976,8 +969,10 @@ extern void* Bsexp (int bn, ...) {
|
|||
__pre_gc();
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
printf("Bsexp: allocate %zu!\n",sizeof(int) * (n+1)); fflush (stdout);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("Bsexp: allocate %zu!\n", sizeof(int) * (n + 1));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
int fields_cnt = n - 1;
|
||||
r = (sexp *)alloc_sexp(fields_cnt);
|
||||
|
|
@ -990,9 +985,7 @@ extern void* Bsexp (int bn, ...) {
|
|||
ai = va_arg(args, int);
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
if (!UNBOXED(ai)) {
|
||||
assert(is_valid_heap_pointer((size_t *) ai));
|
||||
}
|
||||
if (!UNBOXED(ai)) { assert(is_valid_heap_pointer((size_t *)ai)); }
|
||||
#endif
|
||||
|
||||
p = (size_t *)ai;
|
||||
|
|
@ -1004,7 +997,8 @@ extern void* Bsexp (int bn, ...) {
|
|||
#ifdef DEBUG_PRINT
|
||||
r->data_header = SEXP_TAG | ((r->data_header) << 3);
|
||||
print_indent();
|
||||
printf("Bsexp: ends\n"); fflush (stdout);
|
||||
printf("Bsexp: ends\n");
|
||||
fflush(stdout);
|
||||
indent--;
|
||||
#endif
|
||||
|
||||
|
|
@ -1022,10 +1016,12 @@ extern int Btag (void *d, int t, int n) {
|
|||
else {
|
||||
r = TO_DATA(d);
|
||||
#ifndef DEBUG_PRINT
|
||||
return BOX(TAG(r->data_header) == SEXP_TAG && TO_SEXP(d)->tag == UNBOX(t) && LEN(r->data_header) == UNBOX(n));
|
||||
return BOX(TAG(r->data_header) == SEXP_TAG && TO_SEXP(d)->tag == UNBOX(t)
|
||||
&& LEN(r->data_header) == UNBOX(n));
|
||||
#else
|
||||
return BOX(TAG(r->data_header) == SEXP_TAG &&
|
||||
GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(test_small_tree_compaction) && LEN(r->data_header) == UNBOX(n));
|
||||
return BOX(TAG(r->data_header) == SEXP_TAG
|
||||
&& GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(test_small_tree_compaction)
|
||||
&& LEN(r->data_header) == UNBOX(n));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1035,9 +1031,7 @@ int get_tag(data *d) {
|
|||
return TAG(d->data_header);
|
||||
}
|
||||
|
||||
int get_len(data *d) {
|
||||
return LEN(d->data_header);
|
||||
}
|
||||
int get_len (data *d) { return LEN(d->data_header); }
|
||||
|
||||
extern int Barray_patt (void *d, int n) {
|
||||
data *r;
|
||||
|
|
@ -1050,14 +1044,14 @@ extern int Barray_patt (void *d, int n) {
|
|||
}
|
||||
|
||||
extern int Bstring_patt (void *x, void *y) {
|
||||
data *rx = (data *) BOX (NULL),
|
||||
*ry = (data *) BOX (NULL);
|
||||
data *rx = (data *)BOX(NULL), *ry = (data *)BOX(NULL);
|
||||
|
||||
ASSERT_STRING(".string_patt:2", y);
|
||||
|
||||
if (UNBOXED(x)) return BOX(0);
|
||||
else {
|
||||
rx = TO_DATA(x); ry = TO_DATA(y);
|
||||
rx = TO_DATA(x);
|
||||
ry = TO_DATA(y);
|
||||
|
||||
if (TAG(rx->data_header) != STRING_TAG) return BOX(0);
|
||||
|
||||
|
|
@ -1071,14 +1065,9 @@ extern int Bclosure_tag_patt (void *x) {
|
|||
return BOX(TAG(TO_DATA(x)->data_header) == CLOSURE_TAG);
|
||||
}
|
||||
|
||||
extern int Bboxed_patt (void *x) {
|
||||
extern int Bboxed_patt (void *x) { return BOX(UNBOXED(x) ? 0 : 1); }
|
||||
|
||||
return BOX(UNBOXED(x) ? 0 : 1);
|
||||
}
|
||||
|
||||
extern int Bunboxed_patt (void *x) {
|
||||
return BOX(UNBOXED(x) ? 1 : 0);
|
||||
}
|
||||
extern int Bunboxed_patt (void *x) { return BOX(UNBOXED(x) ? 1 : 0); }
|
||||
|
||||
extern int Barray_tag_patt (void *x) {
|
||||
if (UNBOXED(x)) return BOX(0);
|
||||
|
|
@ -1121,9 +1110,7 @@ static void fix_unboxed (char *s, va_list va) {
|
|||
while (*s) {
|
||||
if (*s == '%') {
|
||||
size_t n = p[i];
|
||||
if (UNBOXED (n)) {
|
||||
p[i] = UNBOX(n);
|
||||
}
|
||||
if (UNBOXED(n)) { p[i] = UNBOX(n); }
|
||||
i++;
|
||||
}
|
||||
s++;
|
||||
|
|
@ -1142,7 +1129,10 @@ extern void Bmatch_failure (void *v, char *fname, int line, int col) {
|
|||
createStringBuf();
|
||||
printValue(v);
|
||||
failure("match failure at %s:%d:%d, value '%s'\n",
|
||||
fname, UNBOX(line), UNBOX(col), stringBuf.contents);
|
||||
fname,
|
||||
UNBOX(line),
|
||||
UNBOX(col),
|
||||
stringBuf.contents);
|
||||
}
|
||||
|
||||
extern void * /*Lstrcat*/ Li__Infix_4343 (void *a, void *b) {
|
||||
|
|
@ -1207,8 +1197,7 @@ extern void* LgetEnv (char *var) {
|
|||
char *e = getenv(var);
|
||||
void *s;
|
||||
|
||||
if (e == NULL)
|
||||
return (void*) BOX(0); // TODO add (void*) cast?
|
||||
if (e == NULL) return (void *)BOX(0); // TODO add (void*) cast?
|
||||
|
||||
__pre_gc();
|
||||
|
||||
|
|
@ -1219,9 +1208,7 @@ extern void* LgetEnv (char *var) {
|
|||
return s;
|
||||
}
|
||||
|
||||
extern int Lsystem (char *cmd) {
|
||||
return BOX (system (cmd));
|
||||
}
|
||||
extern int Lsystem (char *cmd) { return BOX(system(cmd)); }
|
||||
|
||||
extern void Lfprintf (FILE *f, char *s, ...) {
|
||||
va_list args = (va_list)BOX(NULL);
|
||||
|
|
@ -1232,9 +1219,7 @@ extern void Lfprintf (FILE *f, char *s, ...) {
|
|||
va_start(args, s);
|
||||
fix_unboxed(s, args);
|
||||
|
||||
if (vfprintf (f, s, args) < 0) {
|
||||
failure ("fprintf (...): %s\n", strerror (errno));
|
||||
}
|
||||
if (vfprintf(f, s, args) < 0) { failure("fprintf (...): %s\n", strerror(errno)); }
|
||||
}
|
||||
|
||||
extern void Lprintf (char *s, ...) {
|
||||
|
|
@ -1245,9 +1230,7 @@ extern void Lprintf (char *s, ...) {
|
|||
va_start(args, s);
|
||||
fix_unboxed(s, args);
|
||||
|
||||
if (vprintf (s, args) < 0) {
|
||||
failure ("fprintf (...): %s\n", strerror (errno));
|
||||
}
|
||||
if (vprintf(s, args) < 0) { failure("fprintf (...): %s\n", strerror(errno)); }
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
|
@ -1260,8 +1243,7 @@ extern FILE* Lfopen (char *f, char *m) {
|
|||
|
||||
h = fopen(f, m);
|
||||
|
||||
if (h)
|
||||
return h;
|
||||
if (h) return h;
|
||||
|
||||
failure("fopen (\"%s\", \"%s\"): %s, %s, %s\n", f, m, strerror(errno));
|
||||
}
|
||||
|
|
@ -1284,8 +1266,7 @@ extern void* LreadLine () {
|
|||
return s;
|
||||
}
|
||||
|
||||
if (errno != 0)
|
||||
failure ("readLine (): %s\n", strerror (errno));
|
||||
if (errno != 0) failure("readLine (): %s\n", strerror(errno));
|
||||
|
||||
return (void *)BOX(0);
|
||||
}
|
||||
|
|
@ -1323,7 +1304,8 @@ extern void Lfwrite (char *fname, char *contents) {
|
|||
f = fopen(fname, "w");
|
||||
|
||||
if (f) {
|
||||
if (fprintf (f, "%s", contents) < 0);
|
||||
if (fprintf(f, "%s", contents) < 0)
|
||||
;
|
||||
else {
|
||||
fclose(f);
|
||||
return;
|
||||
|
|
@ -1345,21 +1327,13 @@ extern void* Lfexists (char *fname) {
|
|||
return (void *)BOX(0); // (void*) cast?
|
||||
}
|
||||
|
||||
extern void* Lfst (void *v) {
|
||||
return Belem (v, BOX(0));
|
||||
}
|
||||
extern void *Lfst (void *v) { return Belem(v, BOX(0)); }
|
||||
|
||||
extern void* Lsnd (void *v) {
|
||||
return Belem (v, BOX(1));
|
||||
}
|
||||
extern void *Lsnd (void *v) { return Belem(v, BOX(1)); }
|
||||
|
||||
extern void* Lhd (void *v) {
|
||||
return Belem (v, BOX(0));
|
||||
}
|
||||
extern void *Lhd (void *v) { return Belem(v, BOX(0)); }
|
||||
|
||||
extern void* Ltl (void *v) {
|
||||
return Belem (v, BOX(1));
|
||||
}
|
||||
extern void *Ltl (void *v) { return Belem(v, BOX(1)); }
|
||||
|
||||
/* Lread is an implementation of the "read" construct */
|
||||
extern int Lread () {
|
||||
|
|
@ -1383,9 +1357,7 @@ extern int Lwrite (int n) {
|
|||
extern int Lrandom (int n) {
|
||||
ASSERT_UNBOXED("Lrandom, 0", n);
|
||||
|
||||
if (UNBOX(n) <= 0) {
|
||||
failure ("invalid range in random: %d\n", UNBOX(n));
|
||||
}
|
||||
if (UNBOX(n) <= 0) { failure("invalid range in random: %d\n", UNBOX(n)); }
|
||||
|
||||
return BOX(random() % UNBOX(n));
|
||||
}
|
||||
|
|
@ -1406,10 +1378,11 @@ extern void set_args (int argc, char *argv[]) {
|
|||
__pre_gc();
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
indent++; print_indent ();
|
||||
printf ("set_args: call: n=%i &p=%p p=%p: ", n, &p, p); fflush(stdout);
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%s ", argv[i]);
|
||||
indent++;
|
||||
print_indent();
|
||||
printf("set_args: call: n=%i &p=%p p=%p: ", n, &p, p);
|
||||
fflush(stdout);
|
||||
for (i = 0; i < n; i++) printf("%s ", argv[i]);
|
||||
printf("EE\n");
|
||||
#endif
|
||||
|
||||
|
|
@ -1419,12 +1392,14 @@ extern void set_args (int argc, char *argv[]) {
|
|||
for (i = 0; i < n; i++) {
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("set_args: iteration %i %p %p ->\n", i, &p, p); fflush(stdout);
|
||||
printf("set_args: iteration %i %p %p ->\n", i, &p, p);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
((int *)p)[i] = (int)Bstring(argv[i]);
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("set_args: iteration %i <- %p %p\n", i, &p, p); fflush(stdout);
|
||||
printf("set_args: iteration %i <- %p %p\n", i, &p, p);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1435,7 +1410,8 @@ extern void set_args (int argc, char *argv[]) {
|
|||
push_extra_root((void **)&global_sysargs);
|
||||
#ifdef DEBUG_PRINT
|
||||
print_indent();
|
||||
printf ("set_args: end\n", n, &p, p); fflush(stdout);
|
||||
printf("set_args: end\n", n, &p, p);
|
||||
fflush(stdout);
|
||||
indent--;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1444,10 +1420,6 @@ extern void set_args (int argc, char *argv[]) {
|
|||
|
||||
static int enable_GC = 1;
|
||||
|
||||
extern void LenableGC () {
|
||||
enable_GC = 1;
|
||||
}
|
||||
extern void LenableGC () { enable_GC = 1; }
|
||||
|
||||
extern void LdisableGC () {
|
||||
enable_GC = 0;
|
||||
}
|
||||
extern void LdisableGC () { enable_GC = 0; }
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
#ifndef __LAMA_RUNTIME__
|
||||
#define __LAMA_RUNTIME__
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <stdarg.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
# include <errno.h>
|
||||
# include <regex.h>
|
||||
# include <time.h>
|
||||
# include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
|
||||
#define WORD_SIZE (CHAR_BIT * sizeof(int))
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#define TAG(x) (x & 0x00000007)
|
||||
//# define TAG(x) (x & 0x00000006)
|
||||
|
||||
|
||||
#define SEXP_ONLY_HEADER_SZ (2 * sizeof(int))
|
||||
|
||||
#ifndef DEBUG_VERSION
|
||||
|
|
@ -44,7 +43,6 @@
|
|||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
|
||||
typedef struct {
|
||||
// store tag in the last three bits to understand what structure this is, other bits are filled with
|
||||
// other utility info (i.e., size for array, number of fields for s-expression)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "gc.h"
|
||||
#include "runtime_common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
|
||||
// function from runtime that maps string to int value
|
||||
|
|
@ -33,12 +34,11 @@ void test_correct_structure_sizes(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void no_gc_tests(void) {
|
||||
test_correct_structure_sizes();
|
||||
}
|
||||
void no_gc_tests (void) { test_correct_structure_sizes(); }
|
||||
|
||||
// unfortunately there is no generic function pointer that can hold pointer to function with arbitrary signature
|
||||
extern size_t call_runtime_function(void *virt_stack_pointer, void *function_pointer, size_t num_args, ...);
|
||||
extern size_t call_runtime_function (void *virt_stack_pointer, void *function_pointer,
|
||||
size_t num_args, ...);
|
||||
|
||||
# include "virt_stack.h"
|
||||
|
||||
|
|
@ -54,6 +54,7 @@ void cleanup_test(virt_stack *st) {
|
|||
vstack_destruct(st);
|
||||
__shutdown();
|
||||
}
|
||||
|
||||
void force_gc_cycle (virt_stack *st) {
|
||||
__gc_stack_top = (size_t)vstack_top(st) - 4;
|
||||
gc_alloc(0);
|
||||
|
|
@ -63,9 +64,7 @@ void force_gc_cycle(virt_stack *st) {
|
|||
void test_simple_string_alloc (void) {
|
||||
virt_stack *st = init_test();
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
vstack_push(st, BOX(i));
|
||||
}
|
||||
for (int i = 0; i < 5; ++i) { vstack_push(st, BOX(i)); }
|
||||
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "abc"));
|
||||
|
||||
|
|
@ -96,7 +95,8 @@ void test_simple_sexp_alloc(void) {
|
|||
|
||||
// allocate sexp with one boxed field and push it onto the stack
|
||||
// calling runtime function Bsexp(BOX(2), BOX(1), LtagHash("test"))
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bsexp, 3, BOX(2), BOX(1), LtagHash("test")));
|
||||
vstack_push(
|
||||
st, call_runtime_function(vstack_top(st) - 4, Bsexp, 3, BOX(2), BOX(1), LtagHash("test")));
|
||||
|
||||
const int N = 10;
|
||||
int ids[N];
|
||||
|
|
@ -123,7 +123,9 @@ void test_simple_closure_alloc(void) {
|
|||
void test_single_object_allocation_with_collection_virtual_stack (void) {
|
||||
virt_stack *st = init_test();
|
||||
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
vstack_push(st,
|
||||
call_runtime_function(
|
||||
vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
|
||||
const int N = 10;
|
||||
int ids[N];
|
||||
|
|
@ -151,7 +153,9 @@ void test_garbage_is_reclaimed(void) {
|
|||
void test_alive_are_not_reclaimed (void) {
|
||||
virt_stack *st = init_test();
|
||||
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
vstack_push(st,
|
||||
call_runtime_function(
|
||||
vstack_top(st) - 4, Bstring, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
|
||||
force_gc_cycle(st);
|
||||
|
||||
|
|
@ -170,7 +174,14 @@ void test_small_tree_compaction(void) {
|
|||
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "left-s"));
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bstring, 1, "right-s"));
|
||||
vstack_push(st, call_runtime_function(vstack_top(st) - 4, Bsexp, 4, BOX(3), vstack_kth_from_start(st, 0), vstack_kth_from_start(st, 1), LtagHash("tree")));
|
||||
vstack_push(st,
|
||||
call_runtime_function(vstack_top(st) - 4,
|
||||
Bsexp,
|
||||
4,
|
||||
BOX(3),
|
||||
vstack_kth_from_start(st, 0),
|
||||
vstack_kth_from_start(st, 1),
|
||||
LtagHash("tree")));
|
||||
force_gc_cycle(st);
|
||||
const int SZ = 10;
|
||||
int ids[SZ];
|
||||
|
|
@ -178,9 +189,7 @@ void test_small_tree_compaction(void) {
|
|||
assert((alive == 3));
|
||||
|
||||
// check that order is indeed preserved
|
||||
for (int i = 0; i < alive - 1; ++i) {
|
||||
assert((ids[i] < ids[i + 1]));
|
||||
}
|
||||
for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
|
||||
cleanup_test(st);
|
||||
}
|
||||
|
||||
|
|
@ -200,22 +209,19 @@ size_t generate_random_obj_forest(virt_stack *st, int cnt, int seed) {
|
|||
|
||||
size_t pos[2] = {rand() % vstack_size(st), rand() % vstack_size(st)};
|
||||
size_t field[2];
|
||||
for (int t = 0; t < 2; ++t) {
|
||||
field[t] = vstack_kth_from_start(st, pos[t]);
|
||||
}
|
||||
for (int t = 0; t < 2; ++t) { field[t] = vstack_kth_from_start(st, pos[t]); }
|
||||
size_t obj;
|
||||
|
||||
if (rand() % 2) {
|
||||
obj = call_runtime_function(vstack_top(st) - 4, Bsexp, 4, BOX(3), field[0], field[1], LtagHash("test"));
|
||||
obj = call_runtime_function(
|
||||
vstack_top(st) - 4, Bsexp, 4, BOX(3), field[0], field[1], LtagHash("test"));
|
||||
} else {
|
||||
obj = BOX(1);
|
||||
}
|
||||
// whether object is stored on stack
|
||||
if (rand() % 2 != 0) {
|
||||
vstack_push(st, obj);
|
||||
if ((obj & 1) == 0) {
|
||||
++alive;
|
||||
}
|
||||
if ((obj & 1) == 0) { ++alive; }
|
||||
}
|
||||
++cur_sz;
|
||||
}
|
||||
|
|
@ -235,9 +241,7 @@ void run_stress_test_random_obj_forest(int seed) {
|
|||
assert(alive == expectedAlive);
|
||||
|
||||
// check that order is indeed preserved
|
||||
for (int i = 0; i < alive - 1; ++i) {
|
||||
assert((ids[i] < ids[i + 1]));
|
||||
}
|
||||
for (int i = 0; i < alive - 1; ++i) { assert((ids[i] < ids[i + 1])); }
|
||||
|
||||
cleanup_test(st);
|
||||
}
|
||||
|
|
@ -263,9 +267,7 @@ int main(int argc, char ** argv) {
|
|||
double diff;
|
||||
time(&start);
|
||||
// stress test
|
||||
for (int s = 0; s < 100; ++s) {
|
||||
run_stress_test_random_obj_forest(s);
|
||||
}
|
||||
for (int s = 0; s < 100; ++s) { run_stress_test_random_obj_forest(s); }
|
||||
time(&end);
|
||||
diff = difftime(end, start);
|
||||
printf("Stress tests took %.2lf seconds to complete\n", diff);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
#include "virt_stack.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
virt_stack *vstack_create() {
|
||||
return malloc(sizeof (virt_stack));
|
||||
}
|
||||
virt_stack *vstack_create () { return malloc(sizeof(virt_stack)); }
|
||||
|
||||
void vstack_destruct(virt_stack *st) {
|
||||
free(st);
|
||||
}
|
||||
void vstack_destruct (virt_stack *st) { free(st); }
|
||||
|
||||
void vstack_init (virt_stack *st) {
|
||||
st->cur = RUNTIME_VSTACK_SIZE;
|
||||
|
|
@ -15,29 +12,21 @@ void vstack_init(virt_stack *st) {
|
|||
}
|
||||
|
||||
void vstack_push (virt_stack *st, size_t value) {
|
||||
if (st->cur == 0) {
|
||||
assert(0);
|
||||
}
|
||||
if (st->cur == 0) { assert(0); }
|
||||
--st->cur;
|
||||
st->buf[st->cur] = value;
|
||||
}
|
||||
|
||||
size_t vstack_pop (virt_stack *st) {
|
||||
if (st->cur == RUNTIME_VSTACK_SIZE) {
|
||||
assert(0);
|
||||
}
|
||||
if (st->cur == RUNTIME_VSTACK_SIZE) { assert(0); }
|
||||
size_t value = st->buf[st->cur];
|
||||
++st->cur;
|
||||
return value;
|
||||
}
|
||||
|
||||
void* vstack_top(virt_stack *st) {
|
||||
return st->buf + st->cur;
|
||||
}
|
||||
void *vstack_top (virt_stack *st) { return st->buf + st->cur; }
|
||||
|
||||
size_t vstack_size(virt_stack *st) {
|
||||
return RUNTIME_VSTACK_SIZE - st->cur;
|
||||
}
|
||||
size_t vstack_size (virt_stack *st) { return RUNTIME_VSTACK_SIZE - st->cur; }
|
||||
|
||||
size_t vstack_kth_from_start (virt_stack *st, size_t k) {
|
||||
assert(vstack_size(st) > k);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
#define LAMA_RUNTIME_VIRT_STACK_H
|
||||
#define RUNTIME_VSTACK_SIZE 100000
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct {
|
||||
size_t buf[RUNTIME_VSTACK_SIZE + 1];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue