2015-04-30 15:56:05 +00:00
/*
* $ Id $
*
2016-02-12 16:23:26 +00:00
Copyright ( c ) 2014 - 2016 Chung , Hyung - Hwan . All rights reserved .
2015-04-30 15:56:05 +00:00
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"
2015-12-17 16:11:10 +00:00
void * stix_allocbytes ( stix_t * stix , stix_oow_t size )
2015-04-30 15:56:05 +00:00
{
stix_uint8_t * ptr ;
2016-06-05 18:01:35 +00:00
# if defined(STIX_DEBUG_GC)
2015-06-21 14:45:45 +00:00
if ( ! ( stix - > option . trait & STIX_NOGC ) ) stix_gc ( stix ) ;
2015-05-07 15:58:04 +00:00
# endif
2015-04-30 15:56:05 +00:00
ptr = stix_allocheapmem ( stix , stix - > curheap , size ) ;
2016-06-13 15:52:09 +00:00
if ( ! ptr & & stix - > errnum = = STIX_EOOMEM & & ! ( stix - > option . trait & STIX_NOGC ) )
2015-04-30 15:56:05 +00:00
{
stix_gc ( stix ) ;
ptr = stix_allocheapmem ( stix , stix - > curheap , size ) ;
2015-05-03 17:10:30 +00:00
/* TODO: grow heap if ptr is still null. */
2015-04-30 15:56:05 +00:00
}
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 ( ) */
2015-05-03 17:10:30 +00:00
hdr = stix_allocbytes ( stix , STIX_SIZEOF ( stix_obj_t ) + nbytes_aligned ) ;
2015-04-30 15:56:05 +00:00
if ( ! hdr ) return STIX_NULL ;
2015-12-27 18:02:59 +00:00
hdr - > _flags = STIX_OBJ_MAKE_FLAGS ( STIX_OBJ_TYPE_OOP , STIX_SIZEOF ( stix_oop_t ) , 0 , 0 , 0 , 0 , 0 ) ;
2015-05-08 14:29:35 +00:00
STIX_OBJ_SET_SIZE ( hdr , size ) ;
STIX_OBJ_SET_CLASS ( hdr , stix - > _nil ) ;
2015-04-30 15:56:05 +00:00
while ( size > 0 ) hdr - > slot [ - - size ] = stix - > _nil ;
return ( stix_oop_t ) hdr ;
}
2015-07-01 15:01:39 +00:00
# if defined(STIX_USE_OBJECT_TRAILER)
2015-10-29 15:24:46 +00:00
stix_oop_t stix_allocoopobjwithtrailer ( stix_t * stix , stix_oow_t size , const stix_oob_t * bptr , stix_oow_t blen )
2015-07-01 15:01:39 +00:00
{
stix_oop_oop_t hdr ;
stix_oow_t nbytes , nbytes_aligned ;
stix_oow_t i ;
/* +1 for the trailer size of the stix_oow_t type */
nbytes = ( size + 1 ) * STIX_SIZEOF ( stix_oop_t ) + blen ;
nbytes_aligned = STIX_ALIGN ( nbytes , STIX_SIZEOF ( stix_oop_t ) ) ;
hdr = stix_allocbytes ( stix , STIX_SIZEOF ( stix_obj_t ) + nbytes_aligned ) ;
if ( ! hdr ) return STIX_NULL ;
2015-12-27 18:02:59 +00:00
hdr - > _flags = STIX_OBJ_MAKE_FLAGS ( STIX_OBJ_TYPE_OOP , STIX_SIZEOF ( stix_oop_t ) , 0 , 0 , 0 , 0 , 1 ) ;
2015-07-01 15:01:39 +00:00
STIX_OBJ_SET_SIZE ( hdr , size ) ;
STIX_OBJ_SET_CLASS ( hdr , stix - > _nil ) ;
for ( i = 0 ; i < size ; i + + ) hdr - > slot [ i ] = stix - > _nil ;
/* [NOTE] this is not converted to a SmallInteger object */
hdr - > slot [ size ] = ( stix_oop_t ) blen ;
if ( bptr )
{
STIX_MEMCPY ( & hdr - > slot [ size + 1 ] , bptr , blen ) ;
}
else
{
STIX_MEMSET ( & hdr - > slot [ size + 1 ] , 0 , blen ) ;
}
return ( stix_oop_t ) hdr ;
}
# endif
2015-10-30 15:36:37 +00:00
static STIX_INLINE 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 )
2015-04-30 15:56:05 +00:00
{
/* 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 ) ) ;
2015-05-08 14:29:35 +00:00
/* TODO: check overflow in size calculation*/
2015-04-30 15:56:05 +00:00
/* 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 ( ) */
2015-05-03 17:10:30 +00:00
hdr = stix_allocbytes ( stix , STIX_SIZEOF ( stix_obj_t ) + nbytes_aligned ) ;
2015-04-30 15:56:05 +00:00
if ( ! hdr ) return STIX_NULL ;
2015-12-27 18:02:59 +00:00
hdr - > _flags = STIX_OBJ_MAKE_FLAGS ( type , unit , extra , 0 , 0 , 0 , 0 ) ;
2015-05-03 17:10:30 +00:00
hdr - > _size = len ;
2015-05-08 14:29:35 +00:00
STIX_OBJ_SET_SIZE ( hdr , len ) ;
STIX_OBJ_SET_CLASS ( hdr , stix - > _nil ) ;
2015-04-30 15:56:05 +00:00
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 ;
}
2015-10-28 14:58:58 +00:00
stix_oop_t stix_alloccharobj ( stix_t * stix , const stix_ooch_t * ptr , stix_oow_t len )
2015-04-30 15:56:05 +00:00
{
2015-10-28 14:58:58 +00:00
return alloc_numeric_array ( stix , ptr , len , STIX_OBJ_TYPE_CHAR , STIX_SIZEOF ( stix_ooch_t ) , 1 ) ;
2015-04-30 15:56:05 +00:00
}
2015-10-30 15:36:37 +00:00
stix_oop_t stix_allocbyteobj ( stix_t * stix , const stix_oob_t * ptr , stix_oow_t len )
2015-07-01 15:01:39 +00:00
{
2015-10-30 15:36:37 +00:00
return alloc_numeric_array ( stix , ptr , len , STIX_OBJ_TYPE_BYTE , STIX_SIZEOF ( stix_oob_t ) , 0 ) ;
2015-07-01 15:01:39 +00:00
}
2015-10-30 15:36:37 +00:00
stix_oop_t stix_allochalfwordobj ( stix_t * stix , const stix_oohw_t * ptr , stix_oow_t len )
2015-04-30 15:56:05 +00:00
{
2015-10-30 15:36:37 +00:00
return alloc_numeric_array ( stix , ptr , len , STIX_OBJ_TYPE_HALFWORD , STIX_SIZEOF ( stix_oohw_t ) , 0 ) ;
2015-04-30 15:56:05 +00:00
}
2015-05-26 16:31:47 +00:00
stix_oop_t stix_allocwordobj ( stix_t * stix , const stix_oow_t * ptr , stix_oow_t len )
2015-04-30 15:56:05 +00:00
{
2015-05-26 16:31:47 +00:00
return alloc_numeric_array ( stix , ptr , len , STIX_OBJ_TYPE_WORD , STIX_SIZEOF ( stix_oow_t ) , 0 ) ;
2015-04-30 15:56:05 +00:00
}
2015-12-27 18:02:59 +00:00
static STIX_INLINE int decode_spec ( stix_t * stix , stix_oop_t _class , stix_oow_t vlen , stix_obj_type_t * type , stix_oow_t * outlen )
2015-04-30 15:56:05 +00:00
{
stix_oow_t spec ;
2015-05-03 17:10:30 +00:00
stix_oow_t named_instvar ;
stix_obj_type_t indexed_type ;
2015-04-30 15:56:05 +00:00
STIX_ASSERT ( STIX_OOP_IS_POINTER ( _class ) ) ;
2015-05-08 14:29:35 +00:00
STIX_ASSERT ( STIX_CLASSOF ( stix , _class ) = = stix - > _class ) ;
2015-04-30 15:56:05 +00:00
2015-11-12 06:57:35 +00:00
STIX_ASSERT ( STIX_OOP_IS_SMOOI ( ( ( stix_oop_class_t ) _class ) - > spec ) ) ;
spec = STIX_OOP_TO_SMOOI ( ( ( stix_oop_class_t ) _class ) - > spec ) ;
2015-04-30 15:56:05 +00:00
2015-05-03 17:10:30 +00:00
named_instvar = STIX_CLASS_SPEC_NAMED_INSTVAR ( spec ) ; /* size of the named_instvar part */
2015-04-30 15:56:05 +00:00
2015-05-03 17:10:30 +00:00
if ( STIX_CLASS_SPEC_IS_INDEXED ( spec ) )
2015-04-30 15:56:05 +00:00
{
2015-05-03 17:10:30 +00:00
indexed_type = STIX_CLASS_SPEC_INDEXED_TYPE ( spec ) ;
if ( indexed_type = = STIX_OBJ_TYPE_OOP )
{
2016-11-18 18:11:13 +00:00
if ( named_instvar > STIX_MAX_NAMED_INSTVARS )
2015-05-03 17:10:30 +00:00
{
2016-11-18 18:11:13 +00:00
STIX_DEBUG3 ( stix , " Too many named instance variables for a variable-pointer class %O - %zu/%zu \n " , _class , named_instvar , ( stix_oow_t ) STIX_MAX_NAMED_INSTVARS ) ;
return - 1 ;
}
if ( vlen > STIX_MAX_INDEXED_INSTVARS ( named_instvar ) )
{
STIX_DEBUG3 ( stix , " Too many unnamed instance variables for a variable-pointer class %O - %zu/%zu \n " , _class , vlen , ( stix_oow_t ) STIX_MAX_INDEXED_INSTVARS ( named_instvar ) ) ;
2015-12-27 18:02:59 +00:00
return - 1 ;
2015-05-03 17:10:30 +00:00
}
2015-12-22 07:49:28 +00:00
STIX_ASSERT ( named_instvar + vlen < = STIX_OBJ_SIZE_MAX ) ;
2015-05-03 17:10:30 +00:00
}
else
{
/* a non-pointer indexed class can't have named instance variables */
2016-11-18 18:11:13 +00:00
if ( named_instvar > 0 )
{
STIX_DEBUG1 ( stix , " Named instance variables in a variable-nonpointer class %O \n " , _class ) ;
return - 1 ;
}
if ( vlen > STIX_OBJ_SIZE_MAX )
{
STIX_DEBUG3 ( stix , " Too many unnamed instance variables for a variable-nonpointer class %O - %zu/%zu \n " , _class , vlen , ( stix_oow_t ) STIX_OBJ_SIZE_MAX ) ;
return - 1 ;
}
2015-05-03 17:10:30 +00:00
}
2015-04-30 15:56:05 +00:00
}
else
{
2015-05-03 17:10:30 +00:00
/* named instance variables only. treat it as if it is an
* indexable class with no variable data */
indexed_type = STIX_OBJ_TYPE_OOP ;
2016-11-18 18:11:13 +00:00
if ( vlen > 0 )
{
STIX_DEBUG2 ( stix , " Unamed instance variables for a fixed class %O - %zu \n " , _class , vlen ) ;
return - 1 ;
}
/*vlen = 0;*/ /* vlen is not used */
if ( named_instvar > STIX_MAX_NAMED_INSTVARS )
{
STIX_DEBUG3 ( stix , " Too many named instance variables for a fixed class %O - %zu/%zu \n " , _class , named_instvar , ( stix_oow_t ) STIX_MAX_NAMED_INSTVARS ) ;
return - 1 ;
}
2015-12-22 07:49:28 +00:00
STIX_ASSERT ( named_instvar < = STIX_OBJ_SIZE_MAX ) ;
2015-04-30 15:56:05 +00:00
}
2015-12-27 18:02:59 +00:00
* type = indexed_type ;
* outlen = named_instvar + vlen ;
return 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_obj_type_t type ;
stix_oow_t alloclen ;
stix_oow_t tmp_count = 0 ;
STIX_ASSERT ( stix - > _nil ! = STIX_NULL ) ;
if ( decode_spec ( stix , _class , vlen , & type , & alloclen ) < = - 1 )
{
stix - > errnum = STIX_EINVAL ;
return STIX_NULL ;
}
2015-05-08 14:29:35 +00:00
stix_pushtmp ( stix , & _class ) ; tmp_count + + ;
2015-05-07 15:58:04 +00:00
2015-12-27 18:02:59 +00:00
switch ( type )
2015-04-30 15:56:05 +00:00
{
case STIX_OBJ_TYPE_OOP :
2015-05-07 15:58:04 +00:00
/* both the fixed part(named instance variables) and
* the variable part ( indexed instance variables ) are allowed . */
2015-12-27 18:02:59 +00:00
oop = stix_allocoopobj ( stix , alloclen ) ;
2015-04-30 15:56:05 +00:00
2015-06-03 17:24:11 +00:00
STIX_ASSERT ( vptr = = STIX_NULL ) ;
/*
This function is not GC - safe . so i don ' t want to initialize
2015-12-02 15:24:13 +00:00
the payload of a pointer object . The caller can call this
function and initialize payloads then .
2015-05-08 14:29:35 +00:00
if ( oop & & vptr & & vlen > 0 )
2015-04-30 15:56:05 +00:00
{
stix_oop_oop_t hdr = ( stix_oop_oop_t ) oop ;
2015-05-03 17:10:30 +00:00
STIX_MEMCPY ( & hdr - > slot [ named_instvar ] , vptr , vlen * STIX_SIZEOF ( stix_oop_t ) ) ;
2015-04-30 15:56:05 +00:00
}
2015-12-02 15:24:13 +00:00
For the above code to work , it should protect the elements of
the vptr array with stix_pushtmp ( ) . So it might be better
to disallow a non - NULL vptr when indexed_type is OOP . See
the assertion above this comment block .
2015-06-03 17:24:11 +00:00
*/
2015-04-30 15:56:05 +00:00
break ;
case STIX_OBJ_TYPE_CHAR :
2015-12-27 18:02:59 +00:00
oop = stix_alloccharobj ( stix , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
2015-05-26 16:31:47 +00:00
case STIX_OBJ_TYPE_BYTE :
2015-12-27 18:02:59 +00:00
oop = stix_allocbyteobj ( stix , vptr , alloclen ) ;
2015-10-30 15:36:37 +00:00
break ;
case STIX_OBJ_TYPE_HALFWORD :
2015-12-27 18:02:59 +00:00
oop = stix_allochalfwordobj ( stix , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
2015-05-26 16:31:47 +00:00
case STIX_OBJ_TYPE_WORD :
2015-12-27 18:02:59 +00:00
oop = stix_allocwordobj ( stix , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
default :
stix - > errnum = STIX_EINTERN ;
2015-05-08 14:29:35 +00:00
oop = STIX_NULL ;
break ;
2015-04-30 15:56:05 +00:00
}
2015-05-08 14:29:35 +00:00
if ( oop ) STIX_OBJ_SET_CLASS ( oop , _class ) ;
stix_poptmps ( stix , tmp_count ) ;
2015-04-30 15:56:05 +00:00
return oop ;
}
2015-07-01 15:01:39 +00:00
2015-12-27 18:02:59 +00:00
stix_oop_t stix_instantiate2 ( stix_t * stix , stix_oop_t _class , const void * vptr , stix_oow_t vlen , int ngc )
2015-07-01 15:01:39 +00:00
{
stix_oop_t oop ;
2015-12-27 18:02:59 +00:00
stix_obj_type_t type ;
stix_oow_t alloclen ;
2015-07-01 15:01:39 +00:00
stix_oow_t tmp_count = 0 ;
STIX_ASSERT ( stix - > _nil ! = STIX_NULL ) ;
2015-12-27 18:02:59 +00:00
if ( decode_spec ( stix , _class , vlen , & type , & alloclen ) < = - 1 )
{
stix - > errnum = STIX_EINVAL ;
return STIX_NULL ;
}
2015-07-01 15:01:39 +00:00
2015-12-27 18:02:59 +00:00
stix_pushtmp ( stix , & _class ) ; tmp_count + + ;
2015-07-01 15:01:39 +00:00
2015-12-27 18:02:59 +00:00
/* TODO: support NGC */
switch ( type )
2015-07-01 15:01:39 +00:00
{
2015-12-27 18:02:59 +00:00
case STIX_OBJ_TYPE_OOP :
/* NOTE: vptr is not used for GC unsafety */
oop = stix_allocoopobj ( stix , alloclen ) ;
break ;
2015-07-01 15:01:39 +00:00
2015-12-27 18:02:59 +00:00
case STIX_OBJ_TYPE_CHAR :
oop = stix_alloccharobj ( stix , vptr , alloclen ) ;
break ;
case STIX_OBJ_TYPE_BYTE :
oop = stix_allocbyteobj ( stix , vptr , alloclen ) ;
break ;
case STIX_OBJ_TYPE_HALFWORD :
oop = stix_allochalfwordobj ( stix , vptr , alloclen ) ;
break ;
case STIX_OBJ_TYPE_WORD :
oop = stix_allocwordobj ( stix , vptr , alloclen ) ;
break ;
default :
stix - > errnum = STIX_EINTERN ;
oop = STIX_NULL ;
break ;
2015-07-01 15:01:39 +00:00
}
2015-12-27 18:02:59 +00:00
if ( oop ) STIX_OBJ_SET_CLASS ( oop , _class ) ;
stix_poptmps ( stix , tmp_count ) ;
return oop ;
}
# if defined(STIX_USE_OBJECT_TRAILER)
stix_oop_t stix_instantiatewithtrailer ( stix_t * stix , stix_oop_t _class , stix_oow_t vlen , const stix_oob_t * tptr , stix_oow_t tlen )
{
stix_oop_t oop ;
stix_obj_type_t type ;
stix_oow_t alloclen ;
stix_oow_t tmp_count = 0 ;
STIX_ASSERT ( stix - > _nil ! = STIX_NULL ) ;
if ( decode_spec ( stix , _class , vlen , & type , & alloclen ) < = - 1 )
{
stix - > errnum = STIX_EINVAL ;
return STIX_NULL ;
2015-07-01 15:01:39 +00:00
}
stix_pushtmp ( stix , & _class ) ; tmp_count + + ;
2015-12-27 18:02:59 +00:00
switch ( type )
2015-07-01 15:01:39 +00:00
{
case STIX_OBJ_TYPE_OOP :
2015-12-27 18:02:59 +00:00
/* NOTE: vptr is not used for GC unsafety */
oop = stix_allocoopobjwithtrailer ( stix , alloclen , tptr , tlen ) ;
2015-07-01 15:01:39 +00:00
break ;
default :
stix - > errnum = STIX_EINTERN ;
oop = STIX_NULL ;
break ;
}
if ( oop ) STIX_OBJ_SET_CLASS ( oop , _class ) ;
stix_poptmps ( stix , tmp_count ) ;
return oop ;
}
# endif
2015-10-30 15:36:37 +00:00