diff --git a/stix/lib/dic.c b/stix/lib/dic.c new file mode 100644 index 0000000..546fa8a --- /dev/null +++ b/stix/lib/dic.c @@ -0,0 +1,166 @@ +/* + * $Id$ + * + Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stix-prv.h" + +static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t old_bucket) +{ + stix_oop_oop_t new_bucket; + stix_oow_t oldsz, newsz, index; + stix_oop_association_t ass; + stix_oop_char_t key; + +/* TODO: derive a better growth size */ + new_bucket = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, STIX_OBJ_GET_SIZE(old_bucket) * 2); + if (!new_bucket) return STIX_NULL; + + oldsz = STIX_OBJ_GET_SIZE(old_bucket); + newsz = STIX_OBJ_GET_SIZE(new_bucket); + + while (oldsz > 0) + { + ass = (stix_oop_association_t)old_bucket->slot[--oldsz]; + if ((stix_oop_t)ass != stix->_nil) + { + STIX_ASSERT (STIX_CLASSOF(stix,ass) == stix->_association); + + key = (stix_oop_char_t)ass->key; + STIX_ASSERT (STIX_CLASSOF(stix,key) == (stix_oop_t)stix->_symbol); + + index = stix_hashchars (key->slot, STIX_OBJ_GET_SIZE(key)) % newsz; + while (new_bucket->slot[index] != stix->_nil) + index = (index + 1) % newsz; + new_bucket->slot[index] = (stix_oop_t)ass; + } + } + + return new_bucket; +} + +stix_oop_t find_or_insert (stix_t* stix, stix_oop_char_t key, stix_oop_t value) +{ + stix_oow_t index, tally; + stix_oop_association_t ass; + stix_oow_t tmp_count = 0; + + /* the system dictionary is not a generic dictionary. + * it accepts only a symbol as a key. */ + STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol); + STIX_ASSERT (STIX_CLASSOF(stix,stix->sysdic->tally) == stix->_small_integer); + STIX_ASSERT (STIX_CLASSOF(stix,stix->sysdic->bucket) == stix->_array); + + index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket); + + while (stix->sysdic->bucket->slot[index] != stix->_nil) + { + ass = (stix_oop_association_t)stix->sysdic->bucket->slot[index]; + + STIX_ASSERT (STIX_CLASSOF(stix,ass) == stix->_association); + STIX_ASSERT (STIX_CLASSOF(stix,ass->key) == stix->_symbol); + + if (STIX_OBJ_GET_SIZE(key) == STIX_OBJ_GET_SIZE(ass->key)) + { + stix_oow_t i; + + for (i = 0; i < STIX_OBJ_GET_SIZE(key); i++) + { + if (key->slot[i] != ((stix_oop_char_t)ass->key)->slot[i]) goto not_equal; + } + return (stix_oop_t)ass; + } + + not_equal: + index = (index + 1) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket); + } + + if (value == STIX_NULL) + { + /* + stix->errnum = STIX_ENOENT; + return STIX_NULL; + */ + return stix->_nil; + } + + stix_pushtmp (stix, (stix_oop_t*)&key); tmp_count++; + stix_pushtmp (stix, &value); tmp_count++; + + tally = STIX_OOP_TO_SMINT(stix->sysdic->tally); + if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->sysdic->bucket)) + { + stix_oop_oop_t bucket; + + /* TODO: make the growth policy configurable instead of growing + it just before it gets full. The polcy can be grow it + if it's 70% full */ + + /* Enlarge the symbol table before it gets full to + * make sure that it has at least one free slot left + * after having added a new symbol. this is to help + * traversal end at a _nil slot if no entry is found. */ + bucket = expand_bucket (stix, stix->sysdic->bucket); + if (!bucket) goto oops; + + stix->sysdic->bucket = bucket; + + /* recalculate the index for the expanded bucket */ + index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket); + + while (stix->sysdic->bucket->slot[index] != stix->_nil) + index = (index + 1) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket); + } + + /* create a new assocation of a key and a value since + * the key isn't found in the root dictionary */ + ass = (stix_oop_association_t)stix_instantiate (stix, stix->_association, STIX_NULL, 0); + if (!ass) + { + ass->key = (stix_oop_t)key; + ass->value = value; + } + + stix->sysdic->tally = STIX_OOP_FROM_SMINT(tally + 1); + stix->sysdic->bucket->slot[index] = (stix_oop_t)ass; + + stix_poptmps (stix, tmp_count); + return (stix_oop_t)ass; + +oops: + stix_poptmps (stix, tmp_count); + return STIX_NULL; +} + +stix_oop_t stix_putatsysdic (stix_t* stix, stix_oop_t key, stix_oop_t value) +{ + STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol); + return find_or_insert (stix, (stix_oop_char_t)key, value); +} + +stix_oop_t stix_getatsysdic (stix_t* stix, stix_oop_t key) +{ + STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol); + return find_or_insert (stix, (stix_oop_char_t)key, STIX_NULL); +} diff --git a/stix/lib/gc.c b/stix/lib/gc.c index 24a2ed3..89f46af 100644 --- a/stix/lib/gc.c +++ b/stix/lib/gc.c @@ -28,63 +28,73 @@ static void cleanup_symbols_for_gc (stix_t* stix, stix_oop_t _nil) { -#if 0 - stix_oop_oop_t buc; - stix_oop_char_t sym; + stix_oop_char_t symbol; stix_oow_t tally, index, i, x, y, z; + stix_oow_t bucket_size; - tally = STIX_OOP_TO_SMINT (stix->symtab->slot[STIX_SYMTAB_TALLY]); +#if defined(STIX_SUPPORT_GC_DURING_IGNITION) + if (!stix->symtab) return; /* symbol table has not been created */ +#endif + + bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket); + + tally = STIX_OOP_TO_SMINT(stix->symtab->tally); if (tally <= 0) return; - buc = (stix_oop_oop_t) stix->symtab->slot[STIX_SYMTAB_BUCKET]; - for (index = 0; index < buc->size; ) + for (index = 0; index < bucket_size; ) { - if (buc->slot[index]->flags & STIX_OBJ_FLAG_MOVED) + if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index])) { index++; continue; } - STIX_ASSERT (buc->slot[index] != _nil); + STIX_ASSERT (stix->symtab->bucket->slot[index] != _nil); +/* { sym = (stix_oop_char_t)buc->slot[index]; wprintf (L">> DISPOSING %d [%S] from the symbol table\n", (int)index, sym->slot); } - for (i = 0, x = index, y = index; i < buc->size; i++) +*/ + + for (i = 0, x = index, y = index; i < bucket_size; i++) { - y = (y + 1) % buc->size; + y = (y + 1) % bucket_size; /* done if the slot at the current hash index is _nil */ - if (buc->slot[y] == _nil) break; + if (stix->symtab->bucket->slot[y] == _nil) break; /* get the natural hash index for the data in the slot * at the current hash index */ - sym = (stix_oop_char_t)buc->slot[y]; + symbol = (stix_oop_char_t)stix->symtab->bucket->slot[y]; - STIX_ASSERT (STIX_CLASSOF(stix,sym) == (stix_oop_t)stix->cc.symbol); + STIX_ASSERT (STIX_CLASSOF(stix,symbol) == stix->_symbol); - z = hash_chars (sym->slot, sym->size) % buc->size; + z = stix_hashchars(symbol->slot, STIX_OBJ_GET_SIZE(symbol)) % bucket_size; /* move an element if necessary */ if ((y > x && (z <= x || z > y)) || (y < x && (z <= x && z > y))) { - buc->slot[x] = buc->slot[y]; + stix->symtab->bucket->slot[x] = stix->symtab->bucket->slot[y]; x = y; } } - buc->slot[x] = _nil; + stix->symtab->bucket->slot[x] = _nil; tally--; } - stix->symtab->slot[STIX_SYMTAB_TALLY] = STIX_OOP_FROM_SMINT(tally); -#endif + stix->symtab->tally = STIX_OOP_FROM_SMINT(tally); } static stix_oop_t move_one (stix_t* stix, stix_oop_t oop) { +#if defined(STIX_SUPPORT_GC_DURING_IGNITION) + if (!oop) return oop; +#endif + STIX_ASSERT (STIX_OOP_IS_POINTER(oop)); if (STIX_OBJ_GET_FLAGS_MOVED(oop)) @@ -93,7 +103,7 @@ static stix_oop_t move_one (stix_t* stix, stix_oop_t oop) * the class field has been updated to the new object * in the 'else' block below. i can simply return it * without further migration. */ - return oop->_class; + return STIX_OBJ_GET_CLASS(oop); } else { @@ -125,8 +135,8 @@ static stix_oop_t move_one (stix_t* stix, stix_oop_t oop) /* let the class field of the old object point to the new * object allocated in the new heap. it is returned in * the 'if' block at the top of this function. */ - oop->_class = tmp; - + STIX_OBJ_SET_CLASS (oop, tmp); + /* return the new object */ return tmp; } @@ -141,11 +151,10 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr) stix_oop_t oop; oop = (stix_oop_t)ptr; - nbytes = (oop->_size + STIX_OBJ_GET_FLAGS_EXTRA(oop)) * STIX_OBJ_GET_FLAGS_UNIT(oop); + nbytes = (STIX_OBJ_GET_SIZE(oop) + STIX_OBJ_GET_FLAGS_EXTRA(oop)) * STIX_OBJ_GET_FLAGS_UNIT(oop); nbytes_aligned = STIX_ALIGN (nbytes, STIX_SIZEOF(stix_oop_t)); - oop->_class = move_one (stix, oop->_class); - + STIX_OBJ_SET_CLASS (oop, move_one(stix, STIX_OBJ_GET_CLASS(oop))); if (STIX_OBJ_GET_FLAGS_TYPE(oop) == STIX_OBJ_TYPE_OOP) { stix_obj_oop_t* xtmp; @@ -157,7 +166,7 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr) xtmp->slot[i] = move_one (stix, xtmp->slot[i]); } } - + /*wprintf (L"ptr in gc => %p size => %d, aligned size => %d\n", ptr, (int)nbytes, (int)nbytes_aligned);*/ ptr = ptr + STIX_SIZEOF(stix_obj_t) + nbytes_aligned; } @@ -174,30 +183,40 @@ void stix_gc (stix_t* stix) * move objects pointed to by the fields to the new heap. * finally perform some tricky symbol table clean-up. */ - stix_uint8_t* ptr; stix_heap_t* tmp; - stix_oop_t old__nil; + stix_oop_t old_nil; + stix_oow_t i; /* TODO: allocate common objects like _nil and the root dictionary * in the permanant heap. minimize moving around */ - - old__nil = stix->_nil; + old_nil = stix->_nil; /* move _nil and the root object table */ - stix->_nil = move_one (stix, stix->_nil); - stix->root = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->root); - stix->_true = move_one (stix, stix->_true); - stix->_false = move_one (stix, stix->_false); + stix->_nil = move_one (stix, stix->_nil); + stix->_true = move_one (stix, stix->_true); + stix->_false = move_one (stix, stix->_false); - stix->cc.array = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.array); - stix->cc.association = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.association); - /*stix->cc.metaclass = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.metaclass);*/ - stix->cc.string = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.string); - stix->cc.symbol = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.symbol); - stix->cc.sysdic = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.sysdic); - stix->cc.numeric[0] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[0]); - stix->cc.numeric[1] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[1]); +/*printf ("BEFORE GC = %p %p %p %p %p %p %p %p %p %p\n", stix->_array, stix->_class, stix->_nil_object, stix->_object, stix->_symbol, stix->_symbol_set, stix->_system_dictionary, stix->_association, stix->_character, stix->_small_integer);*/ + stix->_stix = move_one (stix, stix->_stix); + stix->_class = move_one (stix, stix->_class); + stix->_nil_object = move_one (stix, stix->_nil_object); + stix->_object = move_one (stix, stix->_object); + stix->_array = move_one (stix, stix->_array); + stix->_symbol = move_one (stix, stix->_symbol); + stix->_symbol_set = move_one (stix, stix->_symbol_set); + stix->_system_dictionary = move_one (stix, stix->_system_dictionary); + stix->_association = move_one (stix, stix->_association); + stix->_character = move_one (stix, stix->_character); + stix->_small_integer = move_one (stix, stix->_small_integer); + +/*printf ("AFTER GC = %p %p %p %p %p %p %p %p %p %p\n", stix->_array, stix->_class, stix->_nil_object, stix->_object, stix->_symbol, stix->_symbol_set, stix->_system_dictionary, stix->_association, stix->_character, stix->_small_integer);*/ + stix->sysdic = (stix_oop_set_t) move_one (stix, (stix_oop_t)stix->sysdic); + + for (i = 0; i < stix->tmp_count; i++) + { + *stix->tmp_stack[i] = move_one (stix, *stix->tmp_stack[i]); + } /* scan the new heap to move referenced objects */ ptr = (stix_uint8_t*) STIX_ALIGN ((stix_uintptr_t)stix->newheap->base, STIX_SIZEOF(stix_oop_t)); @@ -207,10 +226,10 @@ void stix_gc (stix_t* stix) * if the symbol has not moved to the new heap, the symbol * is not referenced by any other objects than the symbol * table itself */ - cleanup_symbols_for_gc (stix, old__nil); + cleanup_symbols_for_gc (stix, old_nil); /* move the symbol table itself */ - stix->symtab = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->symtab); + stix->symtab = (stix_oop_set_t)move_one (stix, (stix_oop_t)stix->symtab); /* scan the new heap again from the end position of * the previous scan to move referenced objects by @@ -242,3 +261,24 @@ printf ("===========================\n"); } */ } + + +void stix_pushtmp (stix_t* stix, stix_oop_t* oop_ptr) +{ + /* if you have too many temporaries pushed, something must be wrong. + * change your code not to exceede the stack limit */ + STIX_ASSERT (stix->tmp_count < STIX_COUNTOF(stix->tmp_stack)); + stix->tmp_stack[stix->tmp_count++] = oop_ptr; +} + +void stix_poptmp (stix_t* stix) +{ + STIX_ASSERT (stix->tmp_count > 0); + stix->tmp_count--; +} + +void stix_poptmps (stix_t* stix, stix_oow_t count) +{ + STIX_ASSERT (stix->tmp_count >= count); + stix->tmp_count -= count; +} diff --git a/stix/lib/ignite.c b/stix/lib/ignite.c index 2b85224..664a024 100644 --- a/stix/lib/ignite.c +++ b/stix/lib/ignite.c @@ -27,6 +27,204 @@ #include "stix-prv.h" +#if 0 +stix_oop_t stix_addclass (stix_t* stix, name, spec, ...) +{ +/* convert name to the internal encoding... */ + +/* returned value must be also registered in the system dictionary. + * so it doesn't get GCed. */ + return -1; +} + +int stix_delclass (stix_t* stix, stix_oop_t _class) +{ + stix_oop_class_t c = (stix_oop_class_t)_class; + + if (c->name) + { + /* delete c->name from system dictionary. it'll get GCed if it's not referenced */ + } + + return -1; +} + +stix_oop_t stix_findclass (stix_t* stix, const char* name) +{ + /* find a class object by name */ + return STIX_NULL; +} + +int stix_addmethod (stix_t* stix, stix_oop_t _class, const char* name, const bytecode) +{ + +} +#endif + +/* + * Stix ..................... + * ^ ^ ^ : ....... + * | | | v v : + * | | +------------------- Class ..... + * | | ^ ^ + * | +-------- NilObject ......: : + * | ^........ nil : + * Object ...........................: + * ^ + * | + * + * The class hierarchy is roughly as follows: + * + * Stix + * Class + * NilObject + * Object + * Collection + * IndexedCollection + * FixedSizedCollection + * Array + * ByteArray + * String + * Symbol + * Set + * Dictionary + * SystemDictionary + * SymbolSet + * Magnitude + * Association + * Character + * Number + * Integer + * SmallInteger + * LargeInteger + * + * Stix has no instance variables. + * Stix has 1 class variable: Sysdic + * + */ + +static stix_oop_t alloc_kernel_class (stix_t* stix, stix_oow_t indexed, stix_oow_t spec) +{ + stix_oop_class_t c; + + c = (stix_oop_class_t)stix_allocoopobj (stix, STIX_CLASS_NAMED_INSTVARS + indexed); + if (!c) return STIX_NULL; + + STIX_OBJ_SET_FLAGS_KERNEL (c, 1); + STIX_OBJ_SET_CLASS (c, stix->_class); + c->spec = STIX_OOP_FROM_SMINT(spec); + + return (stix_oop_t)c; +} + +static int ignite_1 (stix_t* stix) +{ + /* + * Create fundamental class objects with some fields mis-initialized yet. + * Such fields include 'superclass', 'subclasses', 'name', etc. + */ + STIX_ASSERT (stix->_nil != STIX_NULL); + STIX_ASSERT (STIX_OBJ_GET_CLASS(stix->_nil) == STIX_NULL); + + /* -------------------------------------------------------------- + * Class + * The instance of Class can have indexed instance variables + * which are actually class variables. + * -------------------------------------------------------------- */ + stix->_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE (STIX_CLASS_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP)); + if (!stix->_class) return -1; + + STIX_ASSERT (STIX_OBJ_GET_CLASS(stix->_class) == STIX_NULL); + STIX_OBJ_SET_CLASS (stix->_class, stix->_class); + + /* -------------------------------------------------------------- + * Stix - proto-object with 1 class variable. + * NilObject - class for the nil object. + * Object - top of all ordinary objects. + * Symbol + * Array + * SymbolSet + * Character + * SmallIntger + * -------------------------------------------------------------- */ + stix->_stix = alloc_kernel_class (stix, 1, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); + stix->_nil_object = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); + stix->_object = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); + stix->_array = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 1, STIX_OBJ_TYPE_OOP)); + stix->_symbol = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 1, STIX_OBJ_TYPE_CHAR)); + stix->_symbol_set = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP)); + stix->_system_dictionary = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP)); + stix->_association = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_ASSOCIATION_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP)); + + /* TOOD: what is a proper spec for Character and SmallInteger? + * If the fixed part is 0, its instance must be an object of 0 payload fields. + * Does this make sense? */ + stix->_character = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); + stix->_small_integer = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); + + if (!stix->_stix || !stix->_nil_object || !stix->_object || + !stix->_array || !stix->_symbol || !stix->_symbol_set || + !stix->_system_dictionary || !stix->_association || + !stix->_character || !stix->_small_integer) return -1; + + STIX_OBJ_SET_CLASS (stix->_nil, stix->_nil_object); + return 0; +} + +static int ignite_2 (stix_t* stix) +{ + stix_oop_oop_t arr; + + /* Create the symbol table */ + stix->symtab = (stix_oop_set_t)stix_instantiate (stix, stix->_symbol_set, STIX_NULL, 0); + if (!stix->symtab) return -1; + + stix->symtab->tally = STIX_OOP_FROM_SMINT(0); + arr = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, stix->option.default_symtab_size); + if (!arr) return -1; + stix->symtab->bucket = arr; + + /* Create the system dictionary */ + stix->sysdic = (stix_oop_set_t)stix_instantiate (stix, stix->_system_dictionary, STIX_NULL, 0); + if (!stix->sysdic) return -1; + + stix->sysdic->tally = STIX_OOP_FROM_SMINT(0); + arr = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, stix->option.default_sysdic_size); + if (!arr) return -1; + stix->sysdic->bucket = arr; + + /* Export the system dictionary via the first class variable of the Stix class */ + ((stix_oop_class_t)stix->_stix)->classvar[0] = (stix_oop_t)stix->sysdic; + + return 0; +} + +#if 0 + +/* + stix_oop_class_t c; + + c = (stix_oop_class_t)stix->_stix; + c->classvar[0] = stix->_nil; +*/ + /* Set subclasses */ + + /* + Set Names. + stix->_stix_object->name = new_symbol ("ProtoObject"); + stix->_nil_object->name = new_symbol ("NilObject"); + stix->_class->name = new_symbol ("Class"); + */ + + /* + _class->instvars = make_string or make_array('spec instmthds classmthds superclass name instvars'); + */ + + /*register 'Stix', 'NilObject' and 'Class' into the system dictionary.*/ + +#endif + + int stix_ignite (stix_t* stix) { STIX_ASSERT (stix->_nil == STIX_NULL); @@ -35,11 +233,11 @@ int stix_ignite (stix_t* stix) if (!stix->_nil) return -1; stix->_nil->_flags = STIX_OBJ_MAKE_FLAGS (STIX_OBJ_TYPE_OOP, STIX_SIZEOF(stix_oop_t), 0, 1, 0); - stix->_nil->_size= 0; - stix->_nil->_class = stix->_nil; + stix->_nil->_size = 0; + if (ignite_1(stix) <= -1 || ignite_2(stix) <= -1) return -1; -printf ("%lu\n", (unsigned long int)stix->_nil->_flags); +/*stix_addclass (stix, "True", spec, "Boolean");*/ /*stix->_true = stix_instantiate (stix, stix->_true_class, STIX_NULL, 0); stix->_false = stix_instantiate (stix, stix->_false_class STIX_NULL, 0); diff --git a/stix/lib/main.c b/stix/lib/main.c new file mode 100644 index 0000000..1302f2e --- /dev/null +++ b/stix/lib/main.c @@ -0,0 +1,115 @@ +#include "stix-prv.h" + +#include +#include + +static void* sys_alloc (stix_mmgr_t* mmgr, stix_size_t size) +{ + return malloc (size); +} + +static void* sys_realloc (stix_mmgr_t* mmgr, void* ptr, stix_size_t size) +{ + return realloc (ptr, size); +} + +static void sys_free (stix_mmgr_t* mmgr, void* ptr) +{ + free (ptr); +} + +static stix_mmgr_t sys_mmgr = +{ + sys_alloc, + sys_realloc, + sys_free, + STIX_NULL +}; + +static void dump_symbol_table (stix_t* stix) +{ + stix_oow_t i, j; + stix_oop_char_t symbol; + + printf ("--------------------------------------------\n"); + printf ("Stix Symbol Table %lu\n", (unsigned long int)STIX_OBJ_GET_SIZE(stix->symtab->bucket)); + printf ("--------------------------------------------\n"); + + for (i = 0; i < STIX_OBJ_GET_SIZE(stix->symtab->bucket); i++) + { + symbol = (stix_oop_char_t)stix->symtab->bucket->slot[i]; + if ((stix_oop_t)symbol != stix->_nil) + { + printf (" %lu [", (unsigned long int)i); + for (j = 0; j < STIX_OBJ_GET_SIZE(symbol); j++) + { + printf ("%c", symbol->slot[j]); + } + printf ("]\n"); + } + } + printf ("--------------------------------------------\n"); +} + +int main (int argc, char* argv[]) +{ + stix_t* stix; + printf ("Stix 1.0.0 - max named %lu max indexed %lu\n", + (unsigned long int)STIX_MAX_NAMED_INSTVARS, (unsigned long int)STIX_MAX_INDEXED_INSTVARS(STIX_MAX_NAMED_INSTVARS)); + + + { + stix_oow_t x; + + printf ("%u\n", STIX_BITS_MAX(unsigned int, 5)); + + x = STIX_CLASS_SPEC_MAKE (10, 1, STIX_OBJ_TYPE_CHAR); + printf ("%lu %lu %lu %lu\n", (unsigned long int)x, (unsigned long int)STIX_OOP_FROM_SMINT(x), + (unsigned long int)STIX_CLASS_SPEC_NAMED_INSTVAR(x), + (unsigned long int)STIX_CLASS_SPEC_INDEXED_TYPE(x)); + } + + stix = stix_open (&sys_mmgr, 0, 1000000lu, STIX_NULL); + if (!stix) + { + printf ("cannot open stix\n"); + return -1; + } + + { + stix_oow_t symtab_size = 5000; + stix_setoption (stix, STIX_DEFAULT_SYMTAB_SIZE, &symtab_size); + stix_setoption (stix, STIX_DEFAULT_SYSDIC_SIZE, &symtab_size); + } + + if (stix_ignite(stix) <= -1) + { + printf ("cannot ignite stix\n"); + stix_close (stix); + return -1; + } + +{ +stix_char_t x[] = { 'S', 't', 'r', 'i', 'n', 'g', '\0' }; +stix_char_t y[] = { 'S', 'y', 'm', 'b', 'o', 'l', '\0' }; +stix_oop_t a, b; + +a = stix_makesymbol (stix, x, 6); +b = stix_makesymbol (stix, y, 6); + +printf ("%p %p\n", a, b); +} + + dump_symbol_table (stix); +stix_gc (stix); + dump_symbol_table (stix); + + stix_close (stix); + +#if defined(__BORLANDC__) + printf ("Press the enter key...\n"); + getchar (); +#endif + + return 0; +} diff --git a/stix/lib/obj.c b/stix/lib/obj.c index f22b53a..3f0c866 100644 --- a/stix/lib/obj.c +++ b/stix/lib/obj.c @@ -30,6 +30,10 @@ void* stix_allocbytes (stix_t* stix, stix_size_t size) { stix_uint8_t* ptr; +#if defined(STIX_DEBUG_GC_1) +stix_gc (stix); +#endif + ptr = stix_allocheapmem (stix, stix->curheap, size); if (!ptr && !(stix->option.trait & STIX_NOGC)) { @@ -135,7 +139,7 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, STIX_ASSERT (stix->_nil != STIX_NULL); STIX_ASSERT (STIX_OOP_IS_POINTER(_class)); - /*STIX_ASSERT (STIX_CLASSOF(_class) == stix->_class); */ + STIX_ASSERT (STIX_CLASSOF(stix, _class) == stix->_class); STIX_ASSERT (STIX_OOP_IS_SMINT(((stix_oop_class_t)_class)->spec)); spec = STIX_OOP_TO_SMINT(((stix_oop_class_t)_class)->spec); @@ -170,15 +174,17 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, if (named_instvar > STIX_MAX_NAMED_INSTVARS) goto einval; } + stix_pushtmp (stix, &_class); + switch (indexed_type) { case STIX_OBJ_TYPE_OOP: - /* class for a variable object. - * both the named_instvar-sized part and the variable part are allowed. */ + /* both the fixed part(named instance variables) and + * the variable part(indexed instance variables) are allowed. */ oop = stix_allocoopobj(stix, named_instvar + vlen); if (!oop) return STIX_NULL; - if (vlen > 0) + if (vptr && vlen > 0) { stix_oop_oop_t hdr = (stix_oop_oop_t)oop; STIX_MEMCPY (&hdr->slot[named_instvar], vptr, vlen * STIX_SIZEOF(stix_oop_t)); @@ -186,13 +192,11 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, break; case STIX_OBJ_TYPE_CHAR: - /* variable-char class can't have instance variables */ oop = stix_alloccharobj(stix, vptr, vlen); if (!oop) return STIX_NULL; break; case STIX_OBJ_TYPE_UINT8: - /* variable-byte class can't have instance variables */ oop = stix_allocuint8obj(stix, vptr, vlen); if (!oop) return STIX_NULL; break; @@ -207,7 +211,9 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, return STIX_NULL; } - oop->_class = _class; + STIX_OBJ_SET_CLASS (oop, _class); + stix_poptmp (stix); + return oop; diff --git a/stix/lib/stix-prv.h b/stix/lib/stix-prv.h index 06f575d..2248767 100644 --- a/stix/lib/stix-prv.h +++ b/stix/lib/stix-prv.h @@ -29,6 +29,12 @@ #include "stix.h" +/* this is useful for debugging. stix_gc() can be called + * while stix has not been fully initialized when this is defined*/ +#define STIX_SUPPORT_GC_DURING_IGNITION +#define STIX_DEBUG_GC_1 + + #include /* TODO: delete these header inclusion lines */ #include #include @@ -40,32 +46,10 @@ #define STIX_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y)) - /* ========================================================================= */ -/* CLASS */ +/* CLASS SPEC ENCODING */ /* ========================================================================= */ -/* The stix_class_t type defines the internal structure of a class object. */ -struct stix_class_t -{ - STIX_OBJ_HEADER; - - stix_oow_t spec; /* SmallInteger */ - stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */ - stix_oop_oop_t classmthds; /* class methods, MethodDictionary */ - stix_oop_oop_t superclass; /* Another class */ - - stix_oop_char_t name; /* Symbol */ - stix_oop_char_t instvars; /* String or Array? */ - stix_oop_char_t classvars; /* String or Array? */ - - /* indexed part afterwards */ -}; - - -typedef struct stix_class_t stix_class_t; -typedef struct stix_class_t* stix_oop_class_t; - /* * The spec field of a class object encodes the number of the fixed part * and the type of the indexed part. The fixed part is the number of @@ -138,20 +122,6 @@ typedef struct stix_class_t* stix_oop_class_t; */ #define STIX_MAX_INDEXED_INSTVARS(named_instvar) ((~(stix_oow_t)0) - named_instvar) - -#define STIX_CLASSOF(stix,oop) \ - (STIX_OOP_IS_NUMERIC(oop)? \ - ((stix_oop_t)(stix)->cc.numeric[((stix_oow_t)oop&3)-1]): \ - (oop)->_class) - -/* -#define STIX_BYTESOF(stix,oop) \ - (STIX_OOP_IS_NUMERIC(oop)? \ - (STIX_SIZEOF(stix_oow_t)): \ - (STIX_SIZEOF(stix_obj_t) + STIX_ALIGN(((oop)->size + (oop)->extra) * (oop)->unit), STIX_SIZEOF(stix_oop_t)) \ - ) -*/ - #if defined(__cplusplus) extern "C" { #endif @@ -191,6 +161,19 @@ void* stix_allocheapmem ( ); +/* ========================================================================= */ +/* stix.c */ +/* ========================================================================= */ +stix_oow_t stix_hashbytes ( + const stix_uint8_t* ptr, + stix_oow_t len +); + +stix_oow_t stix_hashchars ( + const stix_char_t* ptr, + stix_size_t len +); + /* ========================================================================= */ /* obj.c */ /* ========================================================================= */ @@ -199,6 +182,10 @@ void* stix_allocbytes ( stix_size_t size ); +/** + * The stix_allocoopobj() function allocates a raw object composed of \a size + * pointer fields excluding the header. + */ stix_oop_t stix_allocoopobj ( stix_t* stix, stix_oow_t size @@ -222,6 +209,34 @@ stix_oop_t stix_allocuint16obj ( stix_oow_t len ); +/* ========================================================================= */ +/* sym.c */ +/* ========================================================================= */ +stix_oop_t stix_makesymbol ( + stix_t* stix, + const stix_char_t* ptr, + stix_oow_t len +); + +stix_oop_t stix_findsymbol ( + stix_t* stix, + const stix_char_t* ptr, + stix_oow_t len +); + +/* ========================================================================= */ +/* dic.c */ +/* ========================================================================= */ +stix_oop_t stix_putatsysdic ( + stix_t* stix, + stix_oop_t key, + stix_oop_t value +); + +stix_oop_t stix_getatsysdic ( + stix_t* stix, + stix_oop_t key +); #if defined(__cplusplus) } diff --git a/stix/lib/stix.c b/stix/lib/stix.c new file mode 100644 index 0000000..016c695 --- /dev/null +++ b/stix/lib/stix.c @@ -0,0 +1,142 @@ +/* + * $Id$ + * + Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stix-prv.h" + + +stix_t* stix_open (stix_mmgr_t* mmgr, stix_size_t xtnsize, stix_size_t heapsize, stix_errnum_t* errnum) +{ + stix_t* stix; + + stix = STIX_MMGR_ALLOC (mmgr, STIX_SIZEOF(*stix) + xtnsize); + if (stix) + { + if (stix_init(stix, mmgr, heapsize) <= -1) + { + if (errnum) *errnum = stix->errnum; + STIX_MMGR_FREE (mmgr, stix); + stix = STIX_NULL; + } + else STIX_MEMSET (stix + 1, 0, xtnsize); + } + else if (errnum) + { + *errnum = STIX_ENOMEM; + } + + return stix; +} + +void stix_close (stix_t* stix) +{ + stix_fini (stix); + STIX_MMGR_FREE (stix->mmgr, stix); +} + +int stix_init (stix_t* stix, stix_mmgr_t* mmgr, stix_size_t heapsz) +{ + STIX_MEMSET (stix, 0, STIX_SIZEOF(*stix)); + stix->mmgr = mmgr; + + /*stix->permheap = stix_makeheap (stix, what is the best size???); + if (!stix->curheap) goto oops; */ + stix->curheap = stix_makeheap (stix, heapsz); + if (!stix->curheap) goto oops; + stix->newheap = stix_makeheap (stix, heapsz); + if (!stix->newheap) goto oops; + + return 0; + +oops: + if (stix->newheap) stix_killheap (stix, stix->newheap); + if (stix->curheap) stix_killheap (stix, stix->curheap); + if (stix->permheap) stix_killheap (stix, stix->permheap); + return -1; +} + +void stix_fini (stix_t* stix) +{ + stix_killheap (stix, stix->newheap); + stix_killheap (stix, stix->curheap); + stix_killheap (stix, stix->permheap); +} + +int stix_setoption (stix_t* stix, stix_option_t id, const void* value) +{ + switch (id) + { + case STIX_TRAIT: + stix->option.trait = *(const int*)value; + return 0; + + case STIX_DEFAULT_SYMTAB_SIZE: + stix->option.default_symtab_size = *(stix_oow_t*)value; + + case STIX_DEFAULT_SYSDIC_SIZE: + stix->option.default_sysdic_size = *(stix_oow_t*)value; + } + + stix->errnum = STIX_EINVAL; + return -1; +} + +int stix_getoption (stix_t* stix, stix_option_t id, void* value) +{ + switch (id) + { + case STIX_TRAIT: + *(int*)value = stix->option.trait; + return 0; + + case STIX_DEFAULT_SYMTAB_SIZE: + *(stix_oow_t*)value = stix->option.default_symtab_size; + + case STIX_DEFAULT_SYSDIC_SIZE: + *(stix_oow_t*)value = stix->option.default_sysdic_size; + }; + + stix->errnum = STIX_EINVAL; + return -1; +} + + +stix_oow_t stix_hashbytes (const stix_uint8_t* ptr, stix_oow_t len) +{ + stix_oow_t h = 0; + const stix_uint8_t* bp, * be; + + bp = ptr; be = bp + len; + while (bp < be) h = h * 31 + *bp++; + + return h; +} + +stix_oow_t stix_hashchars (const stix_char_t* ptr, stix_size_t len) +{ + return stix_hashbytes ((const stix_uint8_t *)ptr, len * STIX_SIZEOF(*ptr)); +} + + diff --git a/stix/lib/stix.h b/stix/lib/stix.h index 70a3ca8..2798d5a 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -188,7 +188,9 @@ typedef enum stix_errnum_t stix_errnum_t; enum stix_option_t { - STIX_TRAIT + STIX_TRAIT, + STIX_DEFAULT_SYMTAB_SIZE, + STIX_DEFAULT_SYSDIC_SIZE }; typedef enum stix_option_t stix_option_t; @@ -383,53 +385,6 @@ enum stix_code_t typedef enum stix_code_t stix_code_t; -typedef struct stix_heap_t stix_heap_t; - -struct stix_heap_t -{ - stix_uint8_t* base; /* start of a heap */ - stix_uint8_t* limit; /* end of a heap */ - stix_uint8_t* ptr; /* next allocation pointer */ -}; - -typedef struct stix_t stix_t; - -struct stix_t -{ - stix_mmgr_t* mmgr; - stix_errnum_t errnum; - - struct - { - int trait; - } option; - - /* ========================= */ - - stix_heap_t* permheap; - stix_heap_t* curheap; - stix_heap_t* newheap; - - /* ========================= */ - - stix_oop_t _nil; /* pointer to the nil object */ - stix_oop_t _true; - stix_oop_t _false; - - stix_oop_oop_t root; /* pointer to the system dictionary */ - stix_oop_oop_t symtab; /* system-wide symbol table */ - - struct - { - stix_oop_oop_t array; - stix_oop_oop_t association; - /*stix_oop_oop_t metaclass;*/ - stix_oop_oop_t string; - stix_oop_oop_t symbol; - stix_oop_oop_t sysdic; - stix_oop_oop_t numeric[2]; /* [0]: smint [1]: character */ - } cc; /* common kernel classes */ -}; /* @@ -453,6 +408,7 @@ struct stix_t #define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TAG_SMINT | STIX_OOP_TAG_CHAR)) #define STIX_OOP_IS_POINTER(oop) (!STIX_OOP_IS_NUMERIC(oop)) +#define STIX_OOP_GET_TAG(oop) (((stix_oow_t)oop) & STIX_LBMASK(stix_oow_t, STIX_OOP_TAG_BITS)) #define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_SMINT) #define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR) @@ -499,7 +455,7 @@ typedef enum stix_obj_type_t stix_obj_type_t; * moved: 0 or 1. used by GC. * * _size: the number of payload items in an object. - * it doesn't include the header size. + * it doesn't include the header size. * * The total number of bytes occupied by an object can be calculated * with this fomula: @@ -528,15 +484,19 @@ typedef enum stix_obj_type_t stix_obj_type_t; #define STIX_OBJ_GET_FLAGS_TYPE(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS) #define STIX_OBJ_GET_FLAGS_UNIT(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS) #define STIX_OBJ_GET_FLAGS_EXTRA(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS) -#define STIX_OBJ_GET_FLAGS_KERNEL(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_UNIT_BITS), STIX_OBJ_FLAGS_KERNEL_BITS) +#define STIX_OBJ_GET_FLAGS_KERNEL(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS) #define STIX_OBJ_GET_FLAGS_MOVED(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS) #define STIX_OBJ_SET_FLAGS_TYPE(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS, v) #define STIX_OBJ_SET_FLAGS_UNIT(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS, v) #define STIX_OBJ_SET_FLAGS_EXTRA(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS, v) -#define STIX_OBJ_SET_FLAGS_KERNEL(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_UNIT_BITS), STIX_OBJ_FLAGS_KERNEL_BITS, v) +#define STIX_OBJ_SET_FLAGS_KERNEL(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS, v) #define STIX_OBJ_SET_FLAGS_MOVED(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS, v) +#define STIX_OBJ_GET_SIZE(oop) ((oop)->_size) +#define STIX_OBJ_GET_CLASS(oop) ((oop)->_class) +#define STIX_OBJ_SET_CLASS(oop,c) ((oop)->_class = (c)) + /* this macro doesn't check the range of the actual value. * make sure that the value of each bit fields given fall within the number * of defined bits */ @@ -582,8 +542,48 @@ struct stix_obj_uint16_t stix_uint16_t slot[1]; }; -#if 0 +#define STIX_CLASS_NAMED_INSTVARS 8 +struct stix_class_t +{ + STIX_OBJ_HEADER; + stix_oop_t spec; /* SmallInteger */ + stix_oop_t superclass; /* Another class */ + stix_oop_t subclasses; /* Array of subclasses */ + stix_oop_char_t name; /* Symbol */ + stix_oop_char_t instvars; /* String or Array? */ + stix_oop_char_t classvars; /* String or Array? */ + + stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */ + stix_oop_oop_t classmthds; /* class methods, MethodDictionary */ + + /* indexed part afterwards */ + stix_oop_t classvar[1]; /* most classes have not class variables. better to be 0 */ +}; +typedef struct stix_class_t stix_class_t; +typedef struct stix_class_t* stix_oop_class_t; + +#define STIX_SET_NAMED_INSTVARS 2 +struct stix_set_t +{ + STIX_OBJ_HEADER; + stix_oop_t tally; /* SmallInteger */ + stix_oop_oop_t bucket; /* Array */ +}; +typedef struct stix_set_t stix_set_t; +typedef struct stix_set_t* stix_oop_set_t; + +#define STIX_ASSOCIATION_NAMED_INSTVARS 2 +struct stix_association_t +{ + STIX_OBJ_HEADER; + stix_oop_t key; + stix_oop_t value; +}; +typedef struct stix_association_t stix_association_t; +typedef struct stix_association_t* stix_oop_association_t; + +#if 0 /* ----------------------------------------- * class structures for classes known to VM * ----------------------------------------- */ @@ -653,62 +653,75 @@ enum stix_class_desc_t STIX_SYSDIC_BUCKET = STIX_DICTIONARY_BUCKET, STIX_SYSDIC_SIZE = STIX_DICTIONARY_SIZE }; - - - -struct stix_kcinfo_t -{ - const stix_char_t* name; - int super; - int fixed; /* the number of fixed fields */ - int vtype; /* variable class type */ - - int nivars; /* instance variables */ - stix_cstr_t ivars[10]; - - int ncvars; /* class variables */ - stix_cstr_t cvars[10]; - - int ncivars; /* class instance variables */ - stix_cstr_t civars[10]; -}; - -typedef struct stix_kcinfo_t stix_kcinfo_t; - -enum stix_kc_t -{ - STIX_VM_KC_OBJECT, - STIX_VM_KC_UNDEFINED_OBJECT, - STIX_VM_KC_BEHAVIOR, - STIX_VM_KC_CLASS, - STIX_VM_KC_METACLASS, - STIX_VM_KC_BLOCK, - STIX_VM_KC_BOOLEAN, - STIX_VM_KC_TRUE, - STIX_VM_KC_FALSE, - STIX_VM_KC_CONTEXT, - STIX_VM_KC_METHOD, - STIX_VM_KC_MAGNITUDE, - STIX_VM_KC_ASSOCIATION, - STIX_VM_KC_CHARACTER, - STIX_VM_KC_NUMBER, - STIX_VM_KC_INTEGER, - STIX_VM_KC_SMALL_INTEGER, - STIX_VM_KC_LARGE_INTEGER, - STIX_VM_KC_COLLECTION, - STIX_VM_KC_INDEXED_COLLECTION, - STIX_VM_KC_ARRAY, - STIX_VM_KC_BYTE_ARRAY, - STIX_VM_KC_SYMBOL_TABLE, - STIX_VM_KC_DICTIONARY, - STIX_VM_KC_SYSTEM_DICTIONARY, - STIX_VM_KC_STRING, - STIX_VM_KC_SYMBOL, - - STIX_VM_KC_MAX /* indicate the number of kernel classes */ -}; #endif +#define STIX_CLASSOF(stix,oop) ( \ + STIX_OOP_IS_SMINT(oop)? (stix)->_small_integer: \ + STIX_OOP_IS_CHAR(oop)? (stix)->_character: (oop)->_class \ +) + +/* +#define STIX_BYTESOF(stix,oop) \ + (STIX_OOP_IS_NUMERIC(oop)? \ + (STIX_SIZEOF(stix_oow_t)): \ + (STIX_SIZEOF(stix_obj_t) + STIX_ALIGN(((oop)->size + (oop)->extra) * (oop)->unit), STIX_SIZEOF(stix_oop_t)) \ + ) +*/ + +typedef struct stix_heap_t stix_heap_t; + +struct stix_heap_t +{ + stix_uint8_t* base; /* start of a heap */ + stix_uint8_t* limit; /* end of a heap */ + stix_uint8_t* ptr; /* next allocation pointer */ +}; + +typedef struct stix_t stix_t; + +struct stix_t +{ + stix_mmgr_t* mmgr; + stix_errnum_t errnum; + + struct + { + int trait; + stix_oow_t default_symtab_size; + stix_oow_t default_sysdic_size; + } option; + + /* ========================= */ + + stix_heap_t* permheap; /* TODO: put kernel objects to here */ + stix_heap_t* curheap; + stix_heap_t* newheap; + + /* ========================= */ + stix_oop_t _nil; /* pointer to the nil object */ + stix_oop_t _true; + stix_oop_t _false; + + stix_oop_t _stix; /* Stix */ + stix_oop_t _nil_object; /* NilObject */ + stix_oop_t _class; /* Class */ + stix_oop_t _object; /* Object */ + stix_oop_t _symbol; /* Symbol */ + stix_oop_t _array; /* Array */ + stix_oop_t _symbol_set; /* SymbolSet */ + stix_oop_t _system_dictionary; /* SystemDictionary */ + stix_oop_t _association; /* Association */ + stix_oop_t _character; /* Character */ + stix_oop_t _small_integer; /* SmallInteger */ + + stix_oop_set_t symtab; /* system-wide symbol table. instance of SymbolSet */ + stix_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */ + + stix_oop_t* tmp_stack[100]; /* stack for temporaries */ + stix_oow_t tmp_count; +}; + + #if defined(__cplusplus) extern "C" { #endif @@ -796,8 +809,6 @@ STIX_EXPORT stix_oop_t stix_instantiate ( stix_oow_t vlen ); - - /** * The stix_ignite() function creates key initial objects. */ @@ -805,6 +816,24 @@ STIX_EXPORT int stix_ignite ( stix_t* stix ); + +/** + * Temporary OOP management + */ +STIX_EXPORT void stix_pushtmp ( + stix_t* stix, + stix_oop_t* oop_ptr +); + +STIX_EXPORT void stix_poptmp ( + stix_t* stix +); + +STIX_EXPORT void stix_poptmps ( + stix_t* stix, + stix_oow_t count +); + #if defined(__cplusplus) } #endif diff --git a/stix/lib/sym.c b/stix/lib/sym.c new file mode 100644 index 0000000..26eaf8c --- /dev/null +++ b/stix/lib/sym.c @@ -0,0 +1,151 @@ +/* + * $Id$ + * + Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stix-prv.h" + +static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t old_bucket) +{ + stix_oop_oop_t new_bucket; + stix_oow_t oldsz, newsz, index; + stix_oop_char_t symbol; + +/* TODO: derive a better growth size */ + new_bucket = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, STIX_OBJ_GET_SIZE(old_bucket) * 2); + if (!new_bucket) return STIX_NULL; + + oldsz = STIX_OBJ_GET_SIZE(old_bucket); + newsz = STIX_OBJ_GET_SIZE(new_bucket); + + while (oldsz > 0) + { + symbol = (stix_oop_char_t)old_bucket->slot[--oldsz]; + if ((stix_oop_t)symbol != stix->_nil) + { + STIX_ASSERT (STIX_CLASSOF(stix,symbol) == stix->_symbol); + /*STIX_ASSERT (sym->size > 0);*/ + + index = stix_hashchars(symbol->slot, STIX_OBJ_GET_SIZE(symbol)) % newsz; + while (new_bucket->slot[index] != stix->_nil) + index = (index + 1) % newsz; + new_bucket->slot[index] = (stix_oop_t)symbol; + } + } + + return new_bucket; +} + +static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len, int create) +{ + stix_oow_t index, tally; + stix_oop_char_t symbol; + + STIX_ASSERT (len > 0); + if (len <= 0) + { + /* i don't allow an empty symbol name */ + stix->errnum = STIX_EINVAL; + return STIX_NULL; + } + + STIX_ASSERT (STIX_CLASSOF(stix,stix->symtab->bucket) == stix->_array); + index = stix_hashchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket); + + /* find a matching symbol in the open-addressed symbol table */ + while (stix->symtab->bucket->slot[index] != stix->_nil) + { + symbol = (stix_oop_char_t)stix->symtab->bucket->slot[index]; + STIX_ASSERT (STIX_CLASSOF(stix,symbol) == (stix_oop_t)stix->_symbol); + + if (len == STIX_OBJ_GET_SIZE(symbol)) + { + stix_oow_t i; + + for (i = 0; i < len; i++) + { + if (ptr[i] != symbol->slot[i]) goto not_equal; + } + return (stix_oop_t)symbol; + } + + not_equal: + index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket); + } + + if (!create) + { + /* + stix->errnum = STIX_ENOENT; + return STIX_NULL; + */ + return stix->_nil; + } + + tally = STIX_OOP_TO_SMINT(stix->symtab->tally); + if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket)) + { + stix_oop_oop_t bucket; + + /* TODO: make the growth policy configurable instead of growing + it just before it gets full. The polcy can be grow it + if it's 70% full */ + + /* Enlarge the symbol table before it gets full to + * make sure that it has at least one free slot left + * after having added a new symbol. this is to help + * traversal end at a _nil slot if no entry is found. */ + bucket = expand_bucket (stix, stix->symtab->bucket); + if (!bucket) return STIX_NULL; + + stix->symtab->bucket = bucket; + + /* recalculate the index for the expanded bucket */ + index = stix_hashchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket); + + while (stix->symtab->bucket->slot[index] != stix->_nil) + index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket); + } + + /* create a new symbol since it isn't found in the symbol table */ + symbol = (stix_oop_char_t)stix_instantiate (stix, stix->_symbol, ptr, len); + if (symbol) + { + stix->symtab->tally = STIX_OOP_FROM_SMINT(tally + 1); + stix->symtab->bucket->slot[index] = (stix_oop_t)symbol; + } + + return (stix_oop_t)symbol; +} + +stix_oop_t stix_makesymbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len) +{ + return find_or_make_symbol (stix, ptr, len, 1); +} + +stix_oop_t stix_findsymbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len) +{ + return find_or_make_symbol (stix, ptr, len, 0); +} +