added some initial files
This commit is contained in:
parent
028be14776
commit
6e9a47fd5b
245
stix/lib/gc.c
Normal file
245
stix/lib/gc.c
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* $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 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_oow_t tally, index, i, x, y, z;
|
||||
|
||||
tally = STIX_OOP_TO_SMINT (stix->symtab->slot[STIX_SYMTAB_TALLY]);
|
||||
if (tally <= 0) return;
|
||||
|
||||
buc = (stix_oop_oop_t) stix->symtab->slot[STIX_SYMTAB_BUCKET];
|
||||
for (index = 0; index < buc->size; )
|
||||
{
|
||||
if (buc->slot[index]->flags & STIX_OBJ_FLAG_MOVED)
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
STIX_ASSERT (buc->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++)
|
||||
{
|
||||
y = (y + 1) % buc->size;
|
||||
|
||||
/* done if the slot at the current hash index is _nil */
|
||||
if (buc->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];
|
||||
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,sym) == (stix_oop_t)stix->cc.symbol);
|
||||
|
||||
z = hash_chars (sym->slot, sym->size) % buc->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];
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
|
||||
buc->slot[x] = _nil;
|
||||
tally--;
|
||||
}
|
||||
|
||||
stix->symtab->slot[STIX_SYMTAB_TALLY] = STIX_OOP_FROM_SMINT(tally);
|
||||
#endif
|
||||
}
|
||||
|
||||
static stix_oop_t move_one (stix_t* stix, stix_oop_t oop)
|
||||
{
|
||||
STIX_ASSERT (STIX_OOP_IS_POINTER(oop));
|
||||
|
||||
if (oop->flags & STIX_OBJ_FLAG_MOVED)
|
||||
{
|
||||
/* this object has migrated to the new heap.
|
||||
* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
stix_oow_t nbytes, nbytes_aligned;
|
||||
stix_oop_t tmp;
|
||||
|
||||
/* calculate the payload size in bytes */
|
||||
nbytes = (oop->size + oop->extra) * oop->unit;
|
||||
nbytes_aligned = STIX_ALIGN (nbytes, STIX_SIZEOF(stix_oop_t));
|
||||
|
||||
/* allocate space in the new heap */
|
||||
tmp = stix_allocheapmem (
|
||||
stix, stix->newheap, STIX_SIZEOF(stix_obj_t) + nbytes_aligned);
|
||||
|
||||
/* allocation here must not fail because
|
||||
* i'm allocating the new space in a new heap for
|
||||
* moving an existing object in the current heap.
|
||||
*
|
||||
* assuming the new heap is as large as the old heap,
|
||||
* and garbage collection doesn't allocate more objects
|
||||
* than in the old heap, it must not fail. */
|
||||
STIX_ASSERT (tmp != STIX_NULL);
|
||||
|
||||
/* copy the payload to the new object */
|
||||
STIX_MEMCPY (tmp, oop, STIX_SIZEOF(stix_obj_t) + nbytes_aligned);
|
||||
|
||||
/* mark the old object that it has migrated to the new heap */
|
||||
oop->flags |= STIX_OBJ_FLAG_MOVED;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* return the new object */
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
|
||||
{
|
||||
while (ptr < stix->newheap->ptr)
|
||||
{
|
||||
stix_oow_t i;
|
||||
stix_oow_t nbytes, nbytes_aligned;
|
||||
stix_oop_t oop;
|
||||
|
||||
oop = (stix_oop_t)ptr;
|
||||
nbytes = (oop->size + oop->extra) * oop->unit;
|
||||
nbytes_aligned = STIX_ALIGN (nbytes, STIX_SIZEOF(stix_oop_t));
|
||||
|
||||
oop->_class = move_one (stix, oop->_class);
|
||||
|
||||
if (oop->type == STIX_OBJ_TYPE_OOP)
|
||||
{
|
||||
stix_obj_oop_t* xtmp;
|
||||
|
||||
xtmp = (stix_oop_oop_t)oop;
|
||||
for (i = 0; i < oop->size; i++)
|
||||
{
|
||||
if (STIX_OOP_IS_POINTER(xtmp->slot[i]))
|
||||
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;
|
||||
}
|
||||
|
||||
/* return the pointer to the beginning of the free space in the heap */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void stix_gc (stix_t* stix)
|
||||
{
|
||||
/*
|
||||
* move a referenced object to the new heap.
|
||||
* inspect the fields of the moved object in the new heap.
|
||||
* 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;
|
||||
|
||||
/* TODO: allocate common objects like _nil and the root dictionary
|
||||
* in the permanant heap. minimize moving around */
|
||||
|
||||
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->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]);
|
||||
|
||||
/* 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 = scan_new_heap (stix, ptr);
|
||||
|
||||
/* traverse the symbol table for unreferenced symbols.
|
||||
* 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);
|
||||
|
||||
/* move the symbol table itself */
|
||||
stix->symtab = (stix_oop_oop_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
|
||||
* the symbol table. */
|
||||
ptr = scan_new_heap (stix, ptr);
|
||||
|
||||
/* swap the current heap and old heap */
|
||||
tmp = stix->curheap;
|
||||
stix->curheap = stix->newheap;
|
||||
stix->newheap = tmp;
|
||||
|
||||
/*
|
||||
{
|
||||
stix_oow_t index;
|
||||
stix_oop_oop_t buc;
|
||||
printf ("=== SURVIVING SYMBOLS ===\n");
|
||||
buc = (stix_oop_oop_t) stix->symtab->slot[STIX_SYMTAB_BUCKET];
|
||||
for (index = 0; index < buc->size; index++)
|
||||
{
|
||||
if ((stix_oop_t)buc->slot[index] != stix->_nil)
|
||||
{
|
||||
const stix_oop_char_t* p = ((stix_oop_char_t)buc->slot[index])->slot;
|
||||
printf ("SYM [");
|
||||
while (*p) printf ("%c", *p++);
|
||||
printf ("]\n");
|
||||
}
|
||||
}
|
||||
printf ("===========================\n");
|
||||
}
|
||||
*/
|
||||
}
|
78
stix/lib/heap.c
Normal file
78
stix/lib/heap.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* $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_heap_t* stix_makeheap (stix_t* stix, stix_size_t size)
|
||||
{
|
||||
stix_heap_t* heap;
|
||||
|
||||
heap = (stix_heap_t*)STIX_MMGR_ALLOC(stix->mmgr, STIX_SIZEOF(*heap) + size);
|
||||
if (!heap)
|
||||
{
|
||||
stix->errnum = STIX_ENOMEM;
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
STIX_MEMSET (heap, 0, STIX_SIZEOF(*heap) + size);
|
||||
|
||||
heap->base = (stix_uint8_t*)(heap + 1);
|
||||
/* adjust the initial allocation pointer to a multiple of the oop size */
|
||||
heap->ptr = (stix_uint8_t*)STIX_ALIGN(((stix_uintptr_t)heap->base), STIX_SIZEOF(stix_oop_t));
|
||||
heap->limit = heap->base + size;
|
||||
|
||||
STIX_ASSERT (heap->ptr >= heap->base);
|
||||
|
||||
/* if size is too small, heap->ptr may go past heap->limit even at
|
||||
* this moment depending on the alignment of heap->base. subsequent
|
||||
* calls to substix_allocheapmem() are bound to fail. Make sure to
|
||||
* pass a heap size large enough */
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
void stix_killheap (stix_t* stix, stix_heap_t* heap)
|
||||
{
|
||||
STIX_MMGR_FREE (stix->mmgr, heap);
|
||||
}
|
||||
|
||||
void* stix_allocheapmem (stix_t* stix, stix_heap_t* heap, stix_size_t size)
|
||||
{
|
||||
stix_uint8_t* ptr;
|
||||
|
||||
/* check the heap size limit */
|
||||
if (heap->ptr >= heap->limit || heap->limit - heap->ptr < size)
|
||||
{
|
||||
stix->errnum = STIX_ENOMEM;
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
/* allocation is as simple as moving the heap pointer */
|
||||
ptr = heap->ptr;
|
||||
heap->ptr += size;
|
||||
|
||||
return ptr;
|
||||
}
|
209
stix/lib/obj.c
Normal file
209
stix/lib/obj.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* $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 void* alloc_bytes (stix_t* stix, stix_size_t size)
|
||||
{
|
||||
stix_uint8_t* ptr;
|
||||
|
||||
ptr = stix_allocheapmem (stix, stix->curheap, size);
|
||||
if (!ptr && !(stix->option.trait & STIX_NOGC))
|
||||
{
|
||||
stix_gc (stix);
|
||||
ptr = stix_allocheapmem (stix, stix->curheap, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
stix_oop_t stix_allocoopobj (stix_t* stix, stix_oow_t size)
|
||||
{
|
||||
stix_oop_oop_t hdr;
|
||||
stix_oow_t nbytes, nbytes_aligned;
|
||||
|
||||
nbytes = size * STIX_SIZEOF(stix_oop_t);
|
||||
|
||||
/* this isn't really necessary since nbytes must be
|
||||
* aligned already. */
|
||||
nbytes_aligned = STIX_ALIGN(nbytes, STIX_SIZEOF(stix_oop_t));
|
||||
|
||||
/* making the number of bytes to allocate a multiple of
|
||||
* STIX_SIZEOF(stix_oop_t) will guarantee the starting address
|
||||
* of the allocated space to be an even number.
|
||||
* see STIX_OOP_IS_NUMERIC() and STIX_OOP_IS_POINTER() */
|
||||
hdr = alloc_bytes (stix, STIX_SIZEOF(stix_obj_t) + nbytes_aligned);
|
||||
if (!hdr) return STIX_NULL;
|
||||
|
||||
hdr->flags = 0;
|
||||
hdr->type = STIX_OBJ_TYPE_OOP;
|
||||
hdr->extra = 0;
|
||||
hdr->unit = STIX_SIZEOF(stix_oop_t);
|
||||
hdr->size = size;
|
||||
hdr->_class = stix->_nil;
|
||||
|
||||
while (size > 0) hdr->slot[--size] = stix->_nil;
|
||||
|
||||
return (stix_oop_t)hdr;
|
||||
}
|
||||
|
||||
static stix_oop_t alloc_numeric_array (stix_t* stix, const void* ptr, stix_oow_t len, stix_obj_type_t type, stix_oow_t unit, int extra)
|
||||
{
|
||||
/* allocate a variable object */
|
||||
|
||||
stix_oop_t hdr;
|
||||
stix_oow_t xbytes, nbytes, nbytes_aligned;
|
||||
|
||||
xbytes = len * unit;
|
||||
/* 'extra' indicates an extra unit to append at the end.
|
||||
* it's useful to store a string with a terminating null */
|
||||
nbytes = extra? xbytes + len: xbytes;
|
||||
nbytes_aligned = STIX_ALIGN(nbytes, STIX_SIZEOF(stix_oop_t));
|
||||
/* TODO: check overflow in size calculation*/
|
||||
|
||||
/* making the number of bytes to allocate a multiple of
|
||||
* STIX_SIZEOF(stix_oop_t) will guarantee the starting address
|
||||
* of the allocated space to be an even number.
|
||||
* see STIX_OOP_IS_NUMERIC() and STIX_OOP_IS_POINTER() */
|
||||
hdr = alloc_bytes (stix, STIX_SIZEOF(stix_obj_t) + nbytes_aligned);
|
||||
if (!hdr) return STIX_NULL;
|
||||
|
||||
hdr->flags = 0;
|
||||
hdr->type = type;
|
||||
hdr->extra = extra;
|
||||
hdr->unit = unit;
|
||||
hdr->size = len;
|
||||
hdr->_class = stix->_nil;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
/* copy data */
|
||||
STIX_MEMCPY (hdr + 1, ptr, xbytes);
|
||||
STIX_MEMSET ((stix_uint8_t*)(hdr + 1) + xbytes, 0, nbytes_aligned - xbytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize with zeros when the string pointer is not given */
|
||||
STIX_MEMSET ((hdr + 1), 0, nbytes_aligned);
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
stix_oop_t stix_alloccharobj (stix_t* stix, const stix_char_t* ptr, stix_oow_t len)
|
||||
{
|
||||
return alloc_numeric_array (stix, ptr, len, STIX_OBJ_TYPE_CHAR, STIX_SIZEOF(stix_char_t), 1);
|
||||
}
|
||||
|
||||
stix_oop_t stix_allocuint8obj (stix_t* stix, const stix_uint8_t* ptr, stix_oow_t len)
|
||||
{
|
||||
|
||||
return alloc_numeric_array (stix, ptr, len, STIX_OBJ_TYPE_UINT8, STIX_SIZEOF(stix_uint8_t), 0);
|
||||
}
|
||||
|
||||
stix_oop_t stix_allocuint16obj (stix_t* stix, const stix_uint16_t* ptr, stix_oow_t len)
|
||||
{
|
||||
return alloc_numeric_array (stix, ptr, len, STIX_OBJ_TYPE_UINT16, STIX_SIZEOF(stix_uint16_t), 0);
|
||||
}
|
||||
|
||||
stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, stix_oow_t vlen)
|
||||
{
|
||||
stix_oop_t oop;
|
||||
stix_oow_t spec;
|
||||
stix_oow_t fixed;
|
||||
stix_obj_type_t vtype;
|
||||
|
||||
STIX_ASSERT (stix->_nil != STIX_NULL);
|
||||
|
||||
STIX_ASSERT (STIX_OOP_IS_POINTER(_class));
|
||||
/*STIX_ASSERT (STIX_CLASSOF(_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);
|
||||
|
||||
fixed = STIX_CLASS_SPEC_FIXED(spec); /* size of the fixed part */
|
||||
|
||||
if (!STIX_CLASS_SPEC_ISVAR(spec))
|
||||
{
|
||||
/* named instance variables only. treat it as if it is a
|
||||
* variable-pointer class with no variable data */
|
||||
vtype = STIX_OBJ_TYPE_OOP;
|
||||
vlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtype = STIX_CLASS_SPEC_VTYPE(spec);
|
||||
if (vtype != STIX_OBJ_TYPE_OOP && fixed > 0)
|
||||
{
|
||||
/* a variable-non-pointer class can't have named instance variables */
|
||||
stix->errnum = STIX_EINVAL;
|
||||
return STIX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (vtype)
|
||||
{
|
||||
case STIX_OBJ_TYPE_OOP:
|
||||
/* class for a variable object.
|
||||
* both the fixed-sized part and the variable part are allowed. */
|
||||
oop = stix_allocoopobj(stix, fixed + vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
|
||||
if (vlen > 0)
|
||||
{
|
||||
stix_oop_oop_t hdr = (stix_oop_oop_t)oop;
|
||||
STIX_MEMCPY (&hdr->slot[fixed], vptr, vlen * STIX_SIZEOF(stix_oop_t));
|
||||
}
|
||||
break;
|
||||
|
||||
case STIX_OBJ_TYPE_CHAR:
|
||||
/* variable-char class can't have instance variables */
|
||||
STIX_ASSERT (fixed == 0);
|
||||
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 */
|
||||
STIX_ASSERT (fixed == 0);
|
||||
oop = stix_allocuint8obj(stix, vptr, vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
break;
|
||||
|
||||
case STIX_OBJ_TYPE_UINT16:
|
||||
STIX_ASSERT (fixed == 0);
|
||||
oop = stix_allocuint16obj(stix, vptr, vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
stix->errnum = STIX_EINTERN;
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
oop->_class = _class;
|
||||
return oop;
|
||||
}
|
178
stix/lib/stix-prv.h
Normal file
178
stix/lib/stix-prv.h
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* $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.
|
||||
*/
|
||||
|
||||
#ifndef _STIX_PRV_H_
|
||||
#define _STIX_PRV_H_
|
||||
|
||||
#include "stix.h"
|
||||
|
||||
#include <stdio.h> /* TODO: delete these header inclusion lines */
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define STIX_MEMSET(dst,src,size) memset(dst,src,size)
|
||||
#define STIX_MEMCPY(dst,src,size) memcpy(dst,src,size)
|
||||
#define STIX_ASSERT(x) assert(x)
|
||||
|
||||
#define STIX_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y))
|
||||
/* make a low bit mask that can mask off low n bits*/
|
||||
#define STIX_LBMASK(type,n) (~(~((type)0) << (n)))
|
||||
|
||||
/* ========================================================================= */
|
||||
/* CLASS */
|
||||
/* ========================================================================= */
|
||||
|
||||
/* The stix_class_t type defines the internal structure of a class object. */
|
||||
struct stix_class_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_oow_t spec;
|
||||
stix_oop_oop_t methods;
|
||||
stix_oop_oop_t superclass;
|
||||
stix_oop_char_t name;
|
||||
stix_oop_char_t instvars;
|
||||
stix_oop_char_t classvars;
|
||||
|
||||
/* variable 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 size of the fixed part
|
||||
* and the type of the variable part. The fixed part is the number of
|
||||
* instance variables. The variable part can be specified when the object
|
||||
* is instantiated if it is variadic.
|
||||
*
|
||||
* vtype is one of the #stix_obj_type_t enumerators.
|
||||
*
|
||||
* The maximum number of named(fixed) instance variables for a class is:
|
||||
* 2 ^ (BITS-IN-OOW - STIX_OBJ_TYPE_BITS - 1)
|
||||
*
|
||||
* The number of named instance variables can be greater than 0 if the class
|
||||
* is not variable or if it's a variable-pointer class(vtype == STIX_OBJ_TYPE_OOP)
|
||||
*
|
||||
* See also #stix_obj_type_t.
|
||||
*/
|
||||
#define STIX_CLASS_SPEC_MAKE(fixed,variadic,vtype) ( \
|
||||
(((stix_oow_t)(fixed)) << (STIX_OBJ_TYPE_BITS + 1)) | \
|
||||
(((stix_oow_t)(vtype)) << 1) | (((stix_oow_t)variadic) & 1) )
|
||||
|
||||
/* what is the number of named instance variables? */
|
||||
#define STIX_CLASS_SPEC_FIXED(spec) ((spec) >> STIX_OBJ_TYPE_BITS)
|
||||
|
||||
/* is a variable class? */
|
||||
#define STIX_CLASS_SPEC_ISVAR(spec) ((spec) & 1)
|
||||
|
||||
/* if so, what variable class is it? variable-character? variable-pointer? etc? */
|
||||
#define STIX_CLASS_SPEC_VTYPE(spec) ((spec) & (STIX_LBMASK(stix_oow_t, STIX_OBJ_TYPE_BITS) << 1))
|
||||
|
||||
/* VM-level macros */
|
||||
#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
|
||||
|
||||
/* ========================================================================= */
|
||||
/* heap.c */
|
||||
/* ========================================================================= */
|
||||
|
||||
/**
|
||||
* The stix_makeheap() function creates a new heap of the \a size bytes.
|
||||
*
|
||||
* \return heap pointer on success and #STIX_NULL on failure.
|
||||
*/
|
||||
stix_heap_t* stix_makeheap (
|
||||
stix_t* stix,
|
||||
stix_size_t size
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_killheap() function destroys the heap pointed to by \a heap.
|
||||
*/
|
||||
void stix_killheap (
|
||||
stix_t* stix,
|
||||
stix_heap_t* heap
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_allocheapmem() function allocates \a size bytes in the heap pointed
|
||||
* to by \a heap.
|
||||
*
|
||||
* \return memory pointer on success and #STIX_NULL on failure.
|
||||
*/
|
||||
void* stix_allocheapmem (
|
||||
stix_t* stix,
|
||||
stix_heap_t* heap,
|
||||
stix_size_t size
|
||||
);
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* obj.c */
|
||||
/* ========================================================================= */
|
||||
stix_oop_t stix_allocoopobj (
|
||||
stix_t* stix,
|
||||
stix_oow_t size
|
||||
);
|
||||
|
||||
stix_oop_t stix_alloccharobj (
|
||||
stix_t* stix,
|
||||
const stix_char_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
stix_oop_t stix_allocuint8obj (
|
||||
stix_t* stix,
|
||||
const stix_uint8_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
stix_oop_t stix_allocuint16obj (
|
||||
stix_t* stix,
|
||||
const stix_uint16_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
771
stix/lib/stix.h
Normal file
771
stix/lib/stix.h
Normal file
@ -0,0 +1,771 @@
|
||||
/*
|
||||
* $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.
|
||||
*/
|
||||
|
||||
#ifndef _STIX_H_
|
||||
#define _STIX_H_
|
||||
|
||||
/* ========================================================================== */
|
||||
/* TODO: define these types and macros using autoconf */
|
||||
typedef unsigned char stix_uint8_t;
|
||||
typedef unsigned short int stix_uint16_t;
|
||||
/*typedef unsigned int stix_uint32_t;*/
|
||||
#if defined(__MWERKS__) && defined(macintosh)
|
||||
/* the metrowerks codewarrior compiler produces the 'illegal bitfield declaration'
|
||||
* if a non-int type is used in the bit-field declaration */
|
||||
typedef unsigned int stix_uintptr_t;
|
||||
typedef unsigned int stix_size_t;
|
||||
#else
|
||||
typedef unsigned long int stix_uintptr_t;
|
||||
typedef unsigned long int stix_size_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned short int stix_char_t; /* TODO ... wchar_t??? */
|
||||
|
||||
#define STIX_SIZEOF(x) (sizeof(x))
|
||||
#define STIX_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
/**
|
||||
* The STIX_OFFSETOF() macro returns the offset of a field from the beginning
|
||||
* of a structure.
|
||||
*/
|
||||
#define STIX_OFFSETOF(type,member) ((stix_uintptr_t)&((type*)0)->member)
|
||||
|
||||
/**
|
||||
* The STIX_ALIGNOF() macro returns the alignment size of a structure.
|
||||
* Note that this macro may not work reliably depending on the type given.
|
||||
*/
|
||||
#define STIX_ALIGNOF(type) STIX_OFFSETOF(struct { stix_uint8_t d1; type d2; }, d2)
|
||||
/*(sizeof(struct { stix_uint8_t d1; type d2; }) - sizeof(type))*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if (__cplusplus >= 201103L) /* C++11 */
|
||||
# define STIX_NULL nullptr
|
||||
# else
|
||||
# define STIX_NULL (0)
|
||||
# endif
|
||||
#else
|
||||
# define STIX_NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct stix_mmgr_t stix_mmgr_t;
|
||||
|
||||
/**
|
||||
* allocate a memory chunk of the size \a n.
|
||||
* @return pointer to a memory chunk on success, #STIX_NULL on failure.
|
||||
*/
|
||||
typedef void* (*stix_mmgr_alloc_t) (stix_mmgr_t* mmgr, stix_size_t n);
|
||||
/**
|
||||
* resize a memory chunk pointed to by \a ptr to the size \a n.
|
||||
* @return pointer to a memory chunk on success, #STIX_NULL on failure.
|
||||
*/
|
||||
typedef void* (*stix_mmgr_realloc_t) (stix_mmgr_t* mmgr, void* ptr, stix_size_t n);
|
||||
/**
|
||||
* free a memory chunk pointed to by \a ptr.
|
||||
*/
|
||||
typedef void (*stix_mmgr_free_t) (stix_mmgr_t* mmgr, void* ptr);
|
||||
|
||||
/**
|
||||
* The stix_mmgr_t type defines the memory management interface.
|
||||
* As the type is merely a structure, it is just used as a single container
|
||||
* for memory management functions with a pointer to user-defined data.
|
||||
* The user-defined data pointer \a ctx is passed to each memory management
|
||||
* function whenever it is called. You can allocate, reallocate, and free
|
||||
* a memory chunk.
|
||||
*
|
||||
* For example, a stix_xxx_open() function accepts a pointer of the stix_mmgr_t
|
||||
* type and the xxx object uses it to manage dynamic data within the object.
|
||||
*/
|
||||
struct stix_mmgr_t
|
||||
{
|
||||
stix_mmgr_alloc_t alloc; /**< allocation function */
|
||||
stix_mmgr_realloc_t realloc; /**< resizing function */
|
||||
stix_mmgr_free_t free; /**< disposal function */
|
||||
void* ctx; /**< user-defined data pointer */
|
||||
};
|
||||
|
||||
/**
|
||||
* The STIX_MMGR_ALLOC() macro allocates a memory block of the \a size bytes
|
||||
* using the \a mmgr memory manager.
|
||||
*/
|
||||
#define STIX_MMGR_ALLOC(mmgr,size) ((mmgr)->alloc(mmgr,size))
|
||||
|
||||
/**
|
||||
* The STIX_MMGR_REALLOC() macro resizes a memory block pointed to by \a ptr
|
||||
* to the \a size bytes using the \a mmgr memory manager.
|
||||
*/
|
||||
#define STIX_MMGR_REALLOC(mmgr,ptr,size) ((mmgr)->realloc(mmgr,ptr,size))
|
||||
|
||||
/**
|
||||
* The STIX_MMGR_FREE() macro deallocates the memory block pointed to by \a ptr.
|
||||
*/
|
||||
#define STIX_MMGR_FREE(mmgr,ptr) ((mmgr)->free(mmgr,ptr))
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(__WATCOMC__)
|
||||
# define STIX_IMPORT __declspec(dllimport)
|
||||
# define STIX_EXPORT __declspec(dllexport)
|
||||
# define STIX_PRIVATE
|
||||
#elif defined(__GNUC__) && (__GNUC__>=4)
|
||||
# define STIX_IMPORT __attribute__((visibility("default")))
|
||||
# define STIX_EXPORT __attribute__((visibility("default")))
|
||||
# define STIX_PRIVATE __attribute__((visibility("hidden")))
|
||||
/*# define STIX_PRIVATE __attribute__((visibility("internal")))*/
|
||||
#else
|
||||
# define STIX_IMPORT
|
||||
# define STIX_EXPORT
|
||||
# define STIX_PRIVATE
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)
|
||||
# define STIX_INLINE inline
|
||||
# define STIX_HAVE_INLINE
|
||||
#elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__)
|
||||
/* gcc disables inline when -std=c89 or -ansi is used.
|
||||
* so use __inline__ supported by gcc regardless of the options */
|
||||
# define STIX_INLINE /*extern*/ __inline__
|
||||
# define STIX_HAVE_INLINE
|
||||
#else
|
||||
# define STIX_INLINE
|
||||
# undef STIX_HAVE_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/**
|
||||
* The stix_errnum_t type defines the error codes.
|
||||
*/
|
||||
enum stix_errnum_t
|
||||
{
|
||||
STIX_ENOERR, /**< no error */
|
||||
STIX_EOTHER, /**< other error */
|
||||
STIX_ENOIMPL, /**< not implemented */
|
||||
STIX_ESYSERR, /**< subsystem error */
|
||||
STIX_EINTERN, /**< internal error */
|
||||
STIX_ENOMEM, /**< insufficient memory */
|
||||
STIX_EINVAL, /**< invalid parameter or data */
|
||||
STIX_ENOENT /**< no matching entry */
|
||||
};
|
||||
typedef enum stix_errnum_t stix_errnum_t;
|
||||
|
||||
enum stix_option_t
|
||||
{
|
||||
STIX_TRAIT
|
||||
};
|
||||
typedef enum stix_option_t stix_option_t;
|
||||
|
||||
enum stix_trait_t
|
||||
{
|
||||
/* perform no garbage collection when the heap is full.
|
||||
* you still can use stix_gc() explicitly. */
|
||||
STIX_NOGC = (1 << 0)
|
||||
};
|
||||
typedef enum stix_trait_t stix_trait_t;
|
||||
|
||||
/* NOTE: sizeof(stix_oop_t) must be equal to sizeof(stix_oow_t) */
|
||||
typedef stix_uintptr_t stix_oow_t;
|
||||
typedef struct stix_obj_t stix_obj_t;
|
||||
typedef struct stix_obj_t* stix_oop_t;
|
||||
|
||||
/* these are more specialized types for stix_obj_t */
|
||||
typedef struct stix_obj_oop_t stix_obj_oop_t;
|
||||
typedef struct stix_obj_char_t stix_obj_char_t;
|
||||
typedef struct stix_obj_uint8_t stix_obj_uint8_t;
|
||||
typedef struct stix_obj_uint16_t stix_obj_uint16_t;
|
||||
|
||||
/* these are more specialized types for stix_oop_t */
|
||||
typedef struct stix_obj_oop_t* stix_oop_oop_t;
|
||||
typedef struct stix_obj_char_t* stix_oop_char_t;
|
||||
typedef struct stix_obj_uint8_t* stix_oop_uint8_t;
|
||||
typedef struct stix_obj_uint16_t* stix_oop_uint16_t;
|
||||
|
||||
/*
|
||||
* The Smalltalk-80 Bytecodes
|
||||
* Range Bits Function
|
||||
* -------------------------------------------------------------
|
||||
* 0-15 0000iiii Push Receiver Variable #iiii
|
||||
* 16-31 0001iiii Push Temporary Location #iiii
|
||||
* 32-63 001iiiii Push Literal Constant #iiiii
|
||||
* 64-95 010iiiii Push Literal Variable #iiiii
|
||||
* 96-103 01100iii Pop and Store Receiver Variable #iii
|
||||
* 104-111 01101iii Pop and Store Temporary Location #iii
|
||||
* 112-119 01110iii Push (receiver, _true, _false, _nil, -1, 0, 1, 2) [iii]
|
||||
* 120-123 011110ii Return (receiver, _true, _false, _nil) [ii] From Message
|
||||
* 124-125 0111110i Return Stack Top From (Message, Block) [i]
|
||||
* 126-127 0111111i unused
|
||||
* 128 10000000 jjkkkkkk Push (Receiver Variable, Temporary Location, Literal Constant, Literal Variable) [jj] #kkkkkk
|
||||
* 129 10000001 jjkkkkkk Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
|
||||
* 130 10000010 jjkkkkkk Pop and Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
|
||||
* 131 10000011 jjjkkkkk Send Literal Selector #kkkkk With jjj Arguments
|
||||
* 132 10000100 jjjjjjjj kkkkkkkk Send Literal Selector #kkkkkkkk With jjjjjjjj Arguments
|
||||
* 133 10000101 jjjkkkkk Send Literal Selector #kkkkk To Superclass With jjj Arguments
|
||||
* 134 10000110 jjjjjjjj kkkkkkkk Send Literal Selector #kkkkkkkk To Superclass With jjjjjjjj Arguments
|
||||
* 135 10000111 Pop Stack Top
|
||||
* 136 10001000 Duplicate Stack Top
|
||||
* 137 10001001 Push Active Context
|
||||
* 138-143 unused
|
||||
* 144-151 10010iii Jump iii + 1 (i.e., 1 through 8)
|
||||
* 152-159 10011iii Pop and Jump On False iii +1 (i.e., 1 through 8)
|
||||
* 160-167 10100iii jjjjjjjj Jump(iii - 4) *256+jjjjjjjj
|
||||
* 168-171 101010ii jjjjjjjj Pop and Jump On True ii *256+jjjjjjjj
|
||||
* 172-175 101011ii jjjjjjjj Pop and Jump On False ii *256+jjjjjjjj
|
||||
* 176-191 1011iiii Send Arithmetic Message #iiii
|
||||
* 192-207 1100iiii Send Special Message #iiii
|
||||
* 208-223 1101iiii Send Literal Selector #iiii With No Arguments
|
||||
* 224-239 1110iiii Send Literal Selector #iiii With 1 Argument
|
||||
* 240-255 1111iiii Send Literal Selector #iiii With 2 Arguments
|
||||
*/
|
||||
|
||||
/**
|
||||
* The stix_code_t type defines byte-code enumerators.
|
||||
*/
|
||||
enum stix_code_t
|
||||
{
|
||||
/* 0-15 */
|
||||
STIX_PUSH_RECEIVER_VARIABLE = 0x00,
|
||||
|
||||
/* 16-31 */
|
||||
STIX_PUSH_TEMPORARY_LOCATION = 0x10,
|
||||
|
||||
/* 32-63 */
|
||||
STIX_PUSH_LITERAL_CONSTANT = 0x20,
|
||||
|
||||
/* 64-95 */
|
||||
STIX_PUSH_LITERAL_VARIABLE = 0x40,
|
||||
|
||||
/* 96-103 */
|
||||
STIX_POP_STORE_RECEIVER_VARIABLE = 0x60,
|
||||
|
||||
/* 104-111 */
|
||||
STIX_POP_STORE_TEMPORARY_LOCATION = 0x68,
|
||||
|
||||
/* 112-119 */
|
||||
STIX_PUSH_RECEIVER = 0x70,
|
||||
STIX_PUSH_TRUE = 0x71,
|
||||
STIX_PUSH_FALSE = 0x72,
|
||||
STIX_PUSH_NIL = 0x73,
|
||||
STIX_PUSH_MINUSONE = 0x74,
|
||||
STIX_PUSH_ZERO = 0x75,
|
||||
STIX_PUSH_ONE = 0x76,
|
||||
STIX_PUSH_TWO = 0x77,
|
||||
|
||||
/* 120-123 */
|
||||
STIX_RETURN_RECEIVER = 0x78,
|
||||
STIX_RETURN_TRUE = 0x79,
|
||||
STIX_RETURN_FALSE = 0x7A,
|
||||
STIX_RETURN_NIL = 0x7B,
|
||||
|
||||
/* 124-125 */
|
||||
STIX_RETURN_FROM_MESSAGE = 0x7C,
|
||||
STIX_RETURN_FROM_BLOCK = 0x7D,
|
||||
|
||||
/* 128 */
|
||||
STIX_PUSH_EXTENDED = 0x80,
|
||||
|
||||
/* 129 */
|
||||
STIX_STORE_EXTENDED = 0x81,
|
||||
|
||||
/* 130 */
|
||||
STIX_POP_STORE_EXTENDED = 0x82,
|
||||
|
||||
/* 131 */
|
||||
STIX_SEND_TO_SELF = 0x83,
|
||||
|
||||
/* 132 */
|
||||
STIX_SEND_TO_SUPER = 0x84,
|
||||
|
||||
/* 133 */
|
||||
STIX_SEND_TO_SELF_EXTENDED = 0x85,
|
||||
|
||||
/* 134 */
|
||||
STIX_SEND_TO_SUPER_EXTENDED = 0x86,
|
||||
|
||||
/* 135 */
|
||||
STIX_POP_STACK_TOP = 0x87,
|
||||
|
||||
/* 136 */
|
||||
STIX_DUP_STACK_TOP = 0x88,
|
||||
|
||||
/* 137 */
|
||||
STIX_PUSH_ACTIVE_CONTEXT = 0x89,
|
||||
|
||||
/* 138 */
|
||||
STIX_DO_PRIMITIVE = 0x8A,
|
||||
|
||||
/* 144-151 */
|
||||
STIX_JUMP = 0x90,
|
||||
|
||||
/* 152-159 */
|
||||
STIX_POP_JUMP_ON_FALSE = 0x98,
|
||||
|
||||
/* 160-167 */
|
||||
STIX_JUMP_EXTENDED = 0xA0,
|
||||
|
||||
/* 168-171 */
|
||||
STIX_POP_JUMP_ON_TRUE_EXTENDED = 0xA8,
|
||||
|
||||
/* 172-175 */
|
||||
STIX_POP_JUMP_ON_FALSE_EXTENDED = 0xAC,
|
||||
|
||||
#if 0
|
||||
STIX_PUSH_RECEIVER_VARIABLE_EXTENDED = 0x60
|
||||
STIX_PUSH_TEMPORARY_LOCATION_EXTENDED = 0x61
|
||||
STIX_PUSH_LITERAL_CONSTANT_EXTENDED = 0x62
|
||||
STIX_PUSH_LITERAL_VARIABLE_EXTENDED = 0x63
|
||||
STIX_STORE_RECEIVER_VARIABLE_EXTENDED = 0x64
|
||||
STIX_STORE_TEMPORARY_LOCATION_EXTENDED = 0x65
|
||||
|
||||
STIX_POP_STACK_TOP = 0x67
|
||||
STIX_DUPLICATE_STACK_TOP = 0x68
|
||||
STIX_PUSH_ACTIVE_CONTEXT = 0x69
|
||||
STIX_PUSH_NIL = 0x6A
|
||||
STIX_PUSH_TRUE = 0x6B
|
||||
STIX_PUSH_FALSE = 0x6C
|
||||
STIX_PUSH_RECEIVER = 0x6D
|
||||
|
||||
STIX_SEND_TO_SELF = 0x70
|
||||
STIX_SEND_TO_SUPER = 0x71
|
||||
STIX_SEND_TO_SELF_EXTENDED = 0x72
|
||||
STIX_SEND_TO_SUPER_EXTENDED = 0x73
|
||||
|
||||
STIX_RETURN_RECEIVER = 0x78
|
||||
STIX_RETURN_TRUE = 0x79
|
||||
STIX_RETURN_FALSE = 0x7A
|
||||
STIX_RETURN_NIL = 0x7B
|
||||
STIX_RETURN_FROM_MESSAGE = 0x7C
|
||||
STIX_RETURN_FROM_BLOCK = 0x7D
|
||||
|
||||
STIX_DO_PRIMITIVE = 0xF0
|
||||
#endif
|
||||
};
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* OOP encoding
|
||||
* An object pointer(OOP) is an ordinary pointer value to an object.
|
||||
* but some simple numeric values are also encoded into OOP using a simple
|
||||
* bit-shifting and masking.
|
||||
*
|
||||
* A real OOP is stored without any bit-shifting while a non-OOP value encoded
|
||||
* in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
|
||||
* are set to 1 or 2.
|
||||
*
|
||||
* This scheme works because the object allocators aligns the object size to
|
||||
* a multiple of sizeof(stix_oop_t). This way, the 2 least-significant bits
|
||||
* of a real OOP are always 0s.
|
||||
*/
|
||||
|
||||
#define STIX_OOP_TYPE_BITS 2
|
||||
#define STIX_OOP_TYPE_SMINT 1
|
||||
#define STIX_OOP_TYPE_CHAR 2
|
||||
|
||||
#define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TYPE_SMINT | STIX_OOP_TYPE_CHAR))
|
||||
#define STIX_OOP_IS_POINTER(oop) (!STIX_OOP_IS_NUMERIC(oop))
|
||||
|
||||
#define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TYPE_SMINT)
|
||||
#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TYPE_CHAR)
|
||||
#define STIX_OOP_FROM_SMINT(num) ((stix_oop_t)(((num) << STIX_OOP_TYPE_BITS) | STIX_OOP_TYPE_SMINT))
|
||||
#define STIX_OOP_TO_SMINT(oop) (((stix_oow_t)oop) >> STIX_OOP_TYPE_BITS)
|
||||
#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)(((num) << STIX_OOP_TYPE_BITS) | STIX_OOP_TYPE_CHAR))
|
||||
#define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TYPE_BITS)
|
||||
|
||||
/*
|
||||
* Object structure
|
||||
*/
|
||||
#define STIX_OBJ_TYPE_BITS 6
|
||||
#define STIX_OBJ_FLAG_BITS 5
|
||||
#define STIX_OBJ_EXTRA_BITS 1
|
||||
#define STIX_OBJ_UNIT_BITS 4
|
||||
|
||||
enum stix_obj_type_t
|
||||
{
|
||||
STIX_OBJ_TYPE_OOP,
|
||||
STIX_OBJ_TYPE_CHAR,
|
||||
STIX_OBJ_TYPE_UINT8,
|
||||
STIX_OBJ_TYPE_UINT16
|
||||
|
||||
/* NOTE: you can have STIX_OBJ_SHORT, STIX_OBJ_INT
|
||||
* STIX_OBJ_LONG, STIX_OBJ_FLOAT, STIX_OBJ_DOUBLE, etc
|
||||
* type type field being 6 bits long, you can have up to 64 different types.
|
||||
|
||||
STIX_OBJ_TYPE_SHORT,
|
||||
STIX_OBJ_TYPE_INT,
|
||||
STIX_OBJ_TYPE_LONG,
|
||||
STIX_OBJ_TYPE_FLOAT,
|
||||
STIX_OBJ_TYPE_DOUBLE */
|
||||
};
|
||||
typedef enum stix_obj_type_t stix_obj_type_t;
|
||||
|
||||
|
||||
/* KERNEL indicates that the object is known to the virtual
|
||||
* machine. VM doesn't allow layout changes of such objects. */
|
||||
enum stix_obj_flag_t
|
||||
{
|
||||
STIX_OBJ_FLAG_KERNEL = (1 << 0),
|
||||
STIX_OBJ_FLAG_HYBRID = (1 << 1),
|
||||
STIX_OBJ_FLAG_MOVED = (1 << 2)
|
||||
};
|
||||
typedef enum stix_obj_flag_t stix_obj_flag_t;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* type: the type of a payload item.
|
||||
* one of STIX_OBJ_TYPE_OOP, STIX_OBJ_TYPE_CHAR,
|
||||
* STIX_OBJ_TYPE_UINT8, STIX_OBJ_TYPE_UINT16
|
||||
* flags: bitwise-ORed of stix_obj_flag_t
|
||||
* extra: 0 or 1. 1 indicates that the payload contains 1 more
|
||||
* item than the value of the size field. mostly used for a
|
||||
* terminating null in a variable-char object.
|
||||
* unit: the size of a payload item in bytes.
|
||||
* size: the number of payload items in an object.
|
||||
* it doesn't include the header size.
|
||||
*
|
||||
* The total number of bytes occupied by an object can be calculated
|
||||
* with this fomula:
|
||||
* sizeof(stix_obj_t) + ALIGN((size + extra) * unit), sizeof(stix_oop_t))
|
||||
*
|
||||
* The ALIGN() macro is used above since allocation adjusts the payload
|
||||
* size to a multiple of sizeof(stix_oop_t). it assumes that sizeof(stix_obj_t)
|
||||
* is a multiple of sizeof(stix_oop_t). See the STIX_BYTESOF() macro.
|
||||
*
|
||||
* Due to the header structure, an object can only contain items of
|
||||
* homogeneous data types in the payload.
|
||||
*
|
||||
* It's actually possible to split the size field into 2. For example,
|
||||
* the upper half contains the number of oops and the lower half contains
|
||||
* the number of bytes/chars. This way, a variable-byte class or a variable-char
|
||||
* class can have normal instance variables. On the contrary, the actual byte
|
||||
* size calculation and the access to the payload fields become more complex.
|
||||
* Therefore, i've dropped the idea.
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define STIX_OBJ_HEADER \
|
||||
stix_oow_t type: STIX_OBJ_TYPE_BITS; \
|
||||
stix_oow_t flags: STIX_OBJ_FLAG_BITS; \
|
||||
stix_oow_t extra: STIX_OBJ_EXTRA_BITS; \
|
||||
stix_oow_t unit: STIX_OBJ_UNIT_BITS; \
|
||||
stix_oow_t size; \
|
||||
stix_oop_t _class
|
||||
|
||||
struct stix_obj_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
};
|
||||
|
||||
struct stix_obj_oop_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_oop_t slot[1];
|
||||
};
|
||||
|
||||
struct stix_obj_char_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_char_t slot[1];
|
||||
};
|
||||
|
||||
struct stix_obj_uint8_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_uint8_t slot[1];
|
||||
};
|
||||
|
||||
struct stix_obj_uint16_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_uint16_t slot[1];
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
/* -----------------------------------------
|
||||
* class structures for classes known to VM
|
||||
* ----------------------------------------- */
|
||||
enum stix_class_desc_t
|
||||
{
|
||||
/* STIX_XXX_SIZE represents the size of the class. other
|
||||
* enumerators represent the index of instance variables of
|
||||
* the class */
|
||||
|
||||
STIX_ASSOCIATION_KEY = 0,
|
||||
STIX_ASSOCIATION_VALUE,
|
||||
STIX_ASSOCIATION_SIZE,
|
||||
|
||||
STIX_DICTIONARY_TALLY = 0,
|
||||
STIX_DICTIONARY_BUCKET,
|
||||
STIX_DICTIONARY_SIZE,
|
||||
|
||||
STIX_BEHAVIOR_SPEC = 0,
|
||||
STIX_BEHAVIOR_METHODS,
|
||||
STIX_BEHAVIOR_SUPERCLASS,
|
||||
STIX_BEHAVIOR_SUBCLASSES,
|
||||
STIX_BEHAVIOR_SIZE,
|
||||
|
||||
STIX_CLASS_SPEC = 0,
|
||||
STIX_CLASS_METHODS,
|
||||
STIX_CLASS_SUPERCLASS,
|
||||
STIX_CLASS_SUBCLASSES,
|
||||
STIX_CLASS_NAME,
|
||||
STIX_CLASS_INSTANCE_VARIABLES,
|
||||
STIX_CLASS_CLASS_VARIABLES,
|
||||
STIX_CLASS_POOL_DICTIONARIES,
|
||||
STIX_CLASS_SIZE,
|
||||
|
||||
STIX_METACLASS_SPEC = 0,
|
||||
STIX_METACLASS_METHODS,
|
||||
STIX_METACLASS_SUPERCLASS,
|
||||
STIX_METACLASS_SUBCLASSES,
|
||||
STIX_METACLASS_INSTANCE_CLASS,
|
||||
STIX_METACLASS_INSTANCE_VARIABLES,
|
||||
STIX_METACLASS_SIZE,
|
||||
|
||||
STIX_BLOCK_CONTEXT = 0,
|
||||
STIX_BLOCK_ARG_COUNT,
|
||||
STIX_BLOCK_ARG_LOC,
|
||||
STIX_BLOCK_BYTE_POINTER,
|
||||
STIX_BLOCK_SIZE,
|
||||
|
||||
STIX_CONTEXT_STACK = 0,
|
||||
STIX_CONTEXT_STACK_TOP,
|
||||
STIX_CONTEXT_RECEIVER,
|
||||
STIX_CONTEXT_PC,
|
||||
STIX_CONTEXT_METHOD,
|
||||
STIX_CONTEXT_SIZE,
|
||||
|
||||
STIX_METHOD_TEXT = 0,
|
||||
STIX_METHOD_SELECTOR,
|
||||
STIX_METHOD_BYTECODES,
|
||||
STIX_METHOD_TMPCOUNT,
|
||||
STIX_METHOD_ARGCOUNT,
|
||||
STIX_METHOD_SIZE,
|
||||
|
||||
STIX_SYMTAB_TALLY = 0,
|
||||
STIX_SYMTAB_BUCKET,
|
||||
STIX_SYMTAB_SIZE,
|
||||
|
||||
STIX_SYSDIC_TALLY = STIX_DICTIONARY_TALLY,
|
||||
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
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
STIX_EXPORT stix_t* stix_open (
|
||||
stix_mmgr_t* mmgr,
|
||||
stix_size_t xtnsize,
|
||||
stix_size_t heapsize,
|
||||
stix_errnum_t* errnum
|
||||
);
|
||||
|
||||
STIX_EXPORT void stix_close (
|
||||
stix_t* vm
|
||||
);
|
||||
|
||||
STIX_EXPORT int stix_init (
|
||||
stix_t* vm,
|
||||
stix_mmgr_t* mmgr,
|
||||
stix_size_t heapsz
|
||||
);
|
||||
|
||||
STIX_EXPORT void stix_fini (
|
||||
stix_t* vm
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_getoption() function gets the value of an option
|
||||
* specified by \a id into the buffer pointed to by \a value.
|
||||
*
|
||||
* \return 0 on success, -1 on failure
|
||||
*/
|
||||
STIX_EXPORT int stix_getoption (
|
||||
stix_t* vm,
|
||||
stix_option_t id,
|
||||
void* value
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_setoption() function sets the value of an option
|
||||
* specified by \a id to the value pointed to by \a value.
|
||||
*
|
||||
* \return 0 on success, -1 on failure
|
||||
*/
|
||||
STIX_EXPORT int stix_setoption (
|
||||
stix_t* vm,
|
||||
stix_option_t id,
|
||||
const void* value
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_gc() function performs garbage collection.
|
||||
* It is not affected by #STIX_NOGC.
|
||||
*/
|
||||
STIX_EXPORT void stix_gc (
|
||||
stix_t* vm
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_findclass() function searchs the root system dictionary
|
||||
* for a class named \a name. The class object pointer is set to the
|
||||
* memory location pointed to by \a oop.
|
||||
*
|
||||
* \return 0 if found, -1 if not found.
|
||||
*/
|
||||
STIX_EXPORT int stix_findclass (
|
||||
stix_t* vm,
|
||||
const stix_char_t* name,
|
||||
stix_oop_t* oop
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The stix_instantiate() function creates a new object of the class
|
||||
* \a _class. The size of the fixed part is taken from the information
|
||||
* contained in the class defintion. The \a vlen parameter specifies
|
||||
* the length of the variable part. The \a vptr parameter points to
|
||||
* the memory area to copy into the variable part of the new object.
|
||||
* If \a vptr is #STIX_NULL, the variable part is initialized to 0 or
|
||||
* an equivalent value depending on the type.
|
||||
*/
|
||||
STIX_EXPORT stix_oop_t stix_instantiate (
|
||||
stix_t* stix,
|
||||
stix_oop_t _class,
|
||||
const void* vptr,
|
||||
stix_oow_t vlen
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user