added many lines of code for initial loading

This commit is contained in:
hyunghwan.chung 2015-05-07 15:58:04 +00:00
parent c74266293d
commit 0b97fee2c4
9 changed files with 1060 additions and 198 deletions

166
stix/lib/dic.c Normal file
View File

@ -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);
}

View File

@ -28,63 +28,73 @@
static void cleanup_symbols_for_gc (stix_t* stix, stix_oop_t _nil) static void cleanup_symbols_for_gc (stix_t* stix, stix_oop_t _nil)
{ {
#if 0 stix_oop_char_t symbol;
stix_oop_oop_t buc;
stix_oop_char_t sym;
stix_oow_t tally, index, i, x, y, z; 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; if (tally <= 0) return;
buc = (stix_oop_oop_t) stix->symtab->slot[STIX_SYMTAB_BUCKET]; for (index = 0; index < bucket_size; )
for (index = 0; index < buc->size; )
{ {
if (buc->slot[index]->flags & STIX_OBJ_FLAG_MOVED) if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index]))
{ {
index++; index++;
continue; continue;
} }
STIX_ASSERT (buc->slot[index] != _nil); STIX_ASSERT (stix->symtab->bucket->slot[index] != _nil);
/*
{ {
sym = (stix_oop_char_t)buc->slot[index]; sym = (stix_oop_char_t)buc->slot[index];
wprintf (L">> DISPOSING %d [%S] from the symbol table\n", (int)index, sym->slot); 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 */ /* 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 /* get the natural hash index for the data in the slot
* at the current hash index */ * 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 */ /* move an element if necessary */
if ((y > x && (z <= x || z > y)) || if ((y > x && (z <= x || z > y)) ||
(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; x = y;
} }
} }
buc->slot[x] = _nil; stix->symtab->bucket->slot[x] = _nil;
tally--; tally--;
} }
stix->symtab->slot[STIX_SYMTAB_TALLY] = STIX_OOP_FROM_SMINT(tally); stix->symtab->tally = STIX_OOP_FROM_SMINT(tally);
#endif
} }
static stix_oop_t move_one (stix_t* stix, stix_oop_t oop) 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)); STIX_ASSERT (STIX_OOP_IS_POINTER(oop));
if (STIX_OBJ_GET_FLAGS_MOVED(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 * the class field has been updated to the new object
* in the 'else' block below. i can simply return it * in the 'else' block below. i can simply return it
* without further migration. */ * without further migration. */
return oop->_class; return STIX_OBJ_GET_CLASS(oop);
} }
else else
{ {
@ -125,7 +135,7 @@ 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 /* let the class field of the old object point to the new
* object allocated in the new heap. it is returned in * object allocated in the new heap. it is returned in
* the 'if' block at the top of this function. */ * the 'if' block at the top of this function. */
oop->_class = tmp; STIX_OBJ_SET_CLASS (oop, tmp);
/* return the new object */ /* return the new object */
return tmp; return tmp;
@ -141,11 +151,10 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
stix_oop_t oop; stix_oop_t oop;
oop = (stix_oop_t)ptr; 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)); 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) if (STIX_OBJ_GET_FLAGS_TYPE(oop) == STIX_OBJ_TYPE_OOP)
{ {
stix_obj_oop_t* xtmp; stix_obj_oop_t* xtmp;
@ -174,30 +183,40 @@ void stix_gc (stix_t* stix)
* move objects pointed to by the fields to the new heap. * move objects pointed to by the fields to the new heap.
* finally perform some tricky symbol table clean-up. * finally perform some tricky symbol table clean-up.
*/ */
stix_uint8_t* ptr; stix_uint8_t* ptr;
stix_heap_t* tmp; 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 /* TODO: allocate common objects like _nil and the root dictionary
* in the permanant heap. minimize moving around */ * in the permanant heap. minimize moving around */
old_nil = stix->_nil;
old__nil = stix->_nil;
/* move _nil and the root object table */ /* move _nil and the root object table */
stix->_nil = move_one (stix, stix->_nil); 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->_true = move_one (stix, stix->_true);
stix->_false = move_one (stix, stix->_false); stix->_false = move_one (stix, stix->_false);
stix->cc.array = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.array); /*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->cc.association = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.association); stix->_stix = move_one (stix, stix->_stix);
/*stix->cc.metaclass = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.metaclass);*/ stix->_class = move_one (stix, stix->_class);
stix->cc.string = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.string); stix->_nil_object = move_one (stix, stix->_nil_object);
stix->cc.symbol = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.symbol); stix->_object = move_one (stix, stix->_object);
stix->cc.sysdic = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.sysdic); stix->_array = move_one (stix, stix->_array);
stix->cc.numeric[0] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[0]); stix->_symbol = move_one (stix, stix->_symbol);
stix->cc.numeric[1] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[1]); 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 */ /* 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)); 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 * if the symbol has not moved to the new heap, the symbol
* is not referenced by any other objects than the symbol * is not referenced by any other objects than the symbol
* table itself */ * table itself */
cleanup_symbols_for_gc (stix, old__nil); cleanup_symbols_for_gc (stix, old_nil);
/* move the symbol table itself */ /* 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 /* scan the new heap again from the end position of
* the previous scan to move referenced objects by * 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;
}

View File

@ -27,6 +27,204 @@
#include "stix-prv.h" #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) int stix_ignite (stix_t* stix)
{ {
STIX_ASSERT (stix->_nil == STIX_NULL); STIX_ASSERT (stix->_nil == STIX_NULL);
@ -35,11 +233,11 @@ int stix_ignite (stix_t* stix)
if (!stix->_nil) return -1; 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->_flags = STIX_OBJ_MAKE_FLAGS (STIX_OBJ_TYPE_OOP, STIX_SIZEOF(stix_oop_t), 0, 1, 0);
stix->_nil->_size= 0; stix->_nil->_size = 0;
stix->_nil->_class = stix->_nil;
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->_true = stix_instantiate (stix, stix->_true_class, STIX_NULL, 0);
stix->_false = stix_instantiate (stix, stix->_false_class STIX_NULL, 0); stix->_false = stix_instantiate (stix, stix->_false_class STIX_NULL, 0);

115
stix/lib/main.c Normal file
View File

@ -0,0 +1,115 @@
#include "stix-prv.h"
#include <stdio.h>
#include <stdlib.h>
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;
}

View File

@ -30,6 +30,10 @@ void* stix_allocbytes (stix_t* stix, stix_size_t size)
{ {
stix_uint8_t* ptr; stix_uint8_t* ptr;
#if defined(STIX_DEBUG_GC_1)
stix_gc (stix);
#endif
ptr = stix_allocheapmem (stix, stix->curheap, size); ptr = stix_allocheapmem (stix, stix->curheap, size);
if (!ptr && !(stix->option.trait & STIX_NOGC)) 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->_nil != STIX_NULL);
STIX_ASSERT (STIX_OOP_IS_POINTER(_class)); 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)); STIX_ASSERT (STIX_OOP_IS_SMINT(((stix_oop_class_t)_class)->spec));
spec = STIX_OOP_TO_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; if (named_instvar > STIX_MAX_NAMED_INSTVARS) goto einval;
} }
stix_pushtmp (stix, &_class);
switch (indexed_type) switch (indexed_type)
{ {
case STIX_OBJ_TYPE_OOP: case STIX_OBJ_TYPE_OOP:
/* class for a variable object. /* both the fixed part(named instance variables) and
* both the named_instvar-sized part and the variable part are allowed. */ * the variable part(indexed instance variables) are allowed. */
oop = stix_allocoopobj(stix, named_instvar + vlen); oop = stix_allocoopobj(stix, named_instvar + vlen);
if (!oop) return STIX_NULL; if (!oop) return STIX_NULL;
if (vlen > 0) if (vptr && vlen > 0)
{ {
stix_oop_oop_t hdr = (stix_oop_oop_t)oop; stix_oop_oop_t hdr = (stix_oop_oop_t)oop;
STIX_MEMCPY (&hdr->slot[named_instvar], vptr, vlen * STIX_SIZEOF(stix_oop_t)); 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; break;
case STIX_OBJ_TYPE_CHAR: case STIX_OBJ_TYPE_CHAR:
/* variable-char class can't have instance variables */
oop = stix_alloccharobj(stix, vptr, vlen); oop = stix_alloccharobj(stix, vptr, vlen);
if (!oop) return STIX_NULL; if (!oop) return STIX_NULL;
break; break;
case STIX_OBJ_TYPE_UINT8: case STIX_OBJ_TYPE_UINT8:
/* variable-byte class can't have instance variables */
oop = stix_allocuint8obj(stix, vptr, vlen); oop = stix_allocuint8obj(stix, vptr, vlen);
if (!oop) return STIX_NULL; if (!oop) return STIX_NULL;
break; break;
@ -207,7 +211,9 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr,
return STIX_NULL; return STIX_NULL;
} }
oop->_class = _class; STIX_OBJ_SET_CLASS (oop, _class);
stix_poptmp (stix);
return oop; return oop;

View File

@ -29,6 +29,12 @@
#include "stix.h" #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 <stdio.h> /* TODO: delete these header inclusion lines */ #include <stdio.h> /* TODO: delete these header inclusion lines */
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@ -40,32 +46,10 @@
#define STIX_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y)) #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 * 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 * 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_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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #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 */ /* obj.c */
/* ========================================================================= */ /* ========================================================================= */
@ -199,6 +182,10 @@ void* stix_allocbytes (
stix_size_t size 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_oop_t stix_allocoopobj (
stix_t* stix, stix_t* stix,
stix_oow_t size stix_oow_t size
@ -222,6 +209,34 @@ stix_oop_t stix_allocuint16obj (
stix_oow_t len 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) #if defined(__cplusplus)
} }

142
stix/lib/stix.c Normal file
View File

@ -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));
}

View File

@ -188,7 +188,9 @@ typedef enum stix_errnum_t stix_errnum_t;
enum stix_option_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; 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 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_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_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_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_SMINT)
#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR) #define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR)
@ -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_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_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_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_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_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_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_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_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. /* 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 * make sure that the value of each bit fields given fall within the number
* of defined bits */ * of defined bits */
@ -582,8 +542,48 @@ struct stix_obj_uint16_t
stix_uint16_t slot[1]; 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 * class structures for classes known to VM
* ----------------------------------------- */ * ----------------------------------------- */
@ -653,62 +653,75 @@ enum stix_class_desc_t
STIX_SYSDIC_BUCKET = STIX_DICTIONARY_BUCKET, STIX_SYSDIC_BUCKET = STIX_DICTIONARY_BUCKET,
STIX_SYSDIC_SIZE = STIX_DICTIONARY_SIZE 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 #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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@ -796,8 +809,6 @@ STIX_EXPORT stix_oop_t stix_instantiate (
stix_oow_t vlen stix_oow_t vlen
); );
/** /**
* The stix_ignite() function creates key initial objects. * The stix_ignite() function creates key initial objects.
*/ */
@ -805,6 +816,24 @@ STIX_EXPORT int stix_ignite (
stix_t* stix 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) #if defined(__cplusplus)
} }
#endif #endif

151
stix/lib/sym.c Normal file
View File

@ -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);
}