added some initial files

This commit is contained in:
hyunghwan.chung 2015-04-30 15:56:05 +00:00
parent 028be14776
commit 6e9a47fd5b
5 changed files with 1481 additions and 0 deletions

245
stix/lib/gc.c Normal file
View 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
View 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
View 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
View 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
View 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