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