2015-04-30 15:56:05 +00:00
/*
* $ Id $
*
2019-11-19 09:40:26 +00:00
Copyright ( c ) 2014 - 2019 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 .
*/
2017-01-09 09:54:49 +00:00
# include "moo-prv.h"
2015-04-30 15:56:05 +00:00
2020-11-29 16:12:28 +00:00
# if defined(MOO_PROFILE_VM)
# include <sys/time.h>
# include <sys/resource.h> /* getrusage */
# endif
2017-01-09 09:54:49 +00:00
void * moo_allocbytes ( moo_t * moo , moo_oow_t size )
2015-04-30 15:56:05 +00:00
{
2018-02-21 09:35:59 +00:00
# if defined(MOO_BUILD_DEBUG)
2020-10-23 14:25:10 +00:00
/* DEBUG_GC is set but NOGC is not set */
2020-11-27 05:13:02 +00:00
if ( ( moo - > option . trait & ( MOO_TRAIT_DEBUG_GC | MOO_TRAIT_NOGC ) ) = = MOO_TRAIT_DEBUG_GC ) moo_gc ( moo , 1 ) ;
2015-05-07 15:58:04 +00:00
# endif
2020-10-17 07:02:44 +00:00
# if defined(MOO_ENABLE_GC_MARK_SWEEP)
2020-11-25 14:48:26 +00:00
if ( moo - > gc_type = = MOO_GC_TYPE_MARK_SWEEP )
2020-10-17 07:02:44 +00:00
{
2020-11-25 14:48:26 +00:00
moo_gchdr_t * gch ;
2020-10-26 16:43:09 +00:00
2020-11-29 16:12:28 +00:00
# if defined(MOO_PROFILE_VM)
struct rusage ru ;
moo_ntime_t rut ;
getrusage ( RUSAGE_SELF , & ru ) ;
MOO_INIT_NTIME ( & rut , ru . ru_utime . tv_sec , MOO_USEC_TO_NSEC ( ru . ru_utime . tv_usec ) ) ;
# endif
2020-11-25 14:48:26 +00:00
if ( MOO_UNLIKELY ( moo - > igniting ) )
2020-10-17 07:02:44 +00:00
{
2020-11-25 14:48:26 +00:00
gch = ( moo_gchdr_t * ) moo_callocheapmem ( moo , moo - > heap , MOO_SIZEOF ( * gch ) + size ) ;
2020-10-17 07:02:44 +00:00
if ( MOO_UNLIKELY ( ! gch ) ) return MOO_NULL ;
}
2020-11-25 14:48:26 +00:00
else
{
2020-11-27 05:13:02 +00:00
moo_oow_t allocsize ;
2020-11-29 16:12:28 +00:00
int gc_called = 0 ;
allocsize = MOO_SIZEOF ( * gch ) + size ;
2020-11-27 05:13:02 +00:00
2020-11-25 14:48:26 +00:00
if ( moo - > gci . bsz > = moo - > gci . threshold )
{
2020-11-27 05:13:02 +00:00
moo_gc ( moo , 0 ) ;
2020-11-25 14:48:26 +00:00
moo - > gci . threshold = moo - > gci . bsz + 100000 ; /* TODO: change this fomula */
2020-11-29 16:12:28 +00:00
gc_called = 1 ;
2020-11-25 14:48:26 +00:00
}
2020-10-17 07:02:44 +00:00
2020-11-27 05:13:02 +00:00
if ( moo - > gci . lazy_sweep ) moo_gc_ms_sweep_lazy ( moo , allocsize ) ;
2020-11-29 16:12:28 +00:00
gch = ( moo_gchdr_t * ) moo_callocheapmem_noerr ( moo , moo - > heap , allocsize ) ;
if ( ! gch )
2020-11-25 14:48:26 +00:00
{
2020-11-29 16:12:28 +00:00
if ( MOO_UNLIKELY ( moo - > option . trait & MOO_TRAIT_NOGC ) ) goto calloc_heapmem_fail ;
if ( gc_called ) goto sweep_the_rest ;
2020-11-27 05:13:02 +00:00
moo_gc ( moo , 0 ) ;
if ( moo - > gci . lazy_sweep ) moo_gc_ms_sweep_lazy ( moo , allocsize ) ;
2020-11-29 16:12:28 +00:00
gch = ( moo_gchdr_t * ) moo_callocheapmem_noerr ( moo , moo - > heap , allocsize ) ;
2020-11-27 05:13:02 +00:00
if ( MOO_UNLIKELY ( ! gch ) )
{
2020-11-29 16:12:28 +00:00
sweep_the_rest :
2020-11-27 05:13:02 +00:00
if ( moo - > gci . lazy_sweep )
{
moo_gc_ms_sweep_lazy ( moo , MOO_TYPE_MAX ( moo_oow_t ) ) ; /* sweep the rest */
gch = ( moo_gchdr_t * ) moo_callocheapmem ( moo , moo - > heap , allocsize ) ;
if ( MOO_UNLIKELY ( ! gch ) ) return MOO_NULL ;
}
else
{
2020-11-29 16:12:28 +00:00
calloc_heapmem_fail :
moo_seterrnum ( moo , MOO_EOOMEM ) ;
2020-11-27 05:13:02 +00:00
return MOO_NULL ;
}
}
2020-11-25 14:48:26 +00:00
}
}
2020-10-17 07:02:44 +00:00
2020-11-28 15:56:24 +00:00
if ( moo - > gci . lazy_sweep & & moo - > gci . ls . curr = = moo - > gci . b )
{
/* if the lazy sweeping point is at the beginning of the allocation block,
* moo - > gc . ls . prev must get updated */
MOO_ASSERT ( moo , moo - > gci . ls . prev = = MOO_NULL ) ;
moo - > gci . ls . prev = gch ;
}
2020-11-25 14:48:26 +00:00
gch - > next = moo - > gci . b ;
moo - > gci . b = gch ;
moo - > gci . bsz + = size ;
2020-11-29 16:12:28 +00:00
# if defined(MOO_PROFILE_VM)
getrusage ( RUSAGE_SELF , & ru ) ;
MOO_SUB_NTIME_SNS ( & rut , & rut , ru . ru_utime . tv_sec , MOO_USEC_TO_NSEC ( ru . ru_utime . tv_usec ) ) ;
MOO_SUB_NTIME ( & moo - > gci . stat . alloc , & moo - > gci . stat . alloc , & rut ) ; /* do subtraction because rut is negative */
# endif
2020-11-25 14:48:26 +00:00
return ( moo_uint8_t * ) ( gch + 1 ) ;
2018-12-09 07:21:16 +00:00
}
else
2020-11-25 14:48:26 +00:00
# endif
2018-12-09 07:21:16 +00:00
{
2020-11-25 14:48:26 +00:00
moo_uint8_t * ptr ;
if ( MOO_UNLIKELY ( moo - > igniting ) )
{
/* you must increase the size of the permspace if this allocation fails */
ptr = ( moo_uint8_t * ) moo_allocheapspace ( moo , & moo - > heap - > permspace , size ) ;
}
else
2018-12-09 07:21:16 +00:00
{
ptr = ( moo_uint8_t * ) moo_allocheapspace ( moo , & moo - > heap - > curspace , size ) ;
2020-11-25 14:48:26 +00:00
if ( ! ptr & & moo - > errnum = = MOO_EOOMEM & & ! ( moo - > option . trait & MOO_TRAIT_NOGC ) )
{
2020-11-27 05:13:02 +00:00
moo_gc ( moo , 1 ) ;
2020-11-25 14:48:26 +00:00
MOO_LOG4 ( moo , MOO_LOG_GC | MOO_LOG_INFO ,
" GC completed - current heap ptr %p limit %p size %zd free %zd \n " ,
moo - > heap - > curspace . ptr , moo - > heap - > curspace . limit ,
( moo_oow_t ) ( moo - > heap - > curspace . limit - moo - > heap - > curspace . base ) ,
( moo_oow_t ) ( moo - > heap - > curspace . limit - moo - > heap - > curspace . ptr )
) ;
ptr = ( moo_uint8_t * ) moo_allocheapspace ( moo , & moo - > heap - > curspace , size ) ;
/* TODO: grow heap if ptr is still null. */
}
2018-12-09 07:21:16 +00:00
}
2020-10-17 07:02:44 +00:00
2020-11-25 14:48:26 +00:00
return ptr ;
}
2015-04-30 15:56:05 +00:00
}
2017-01-09 09:54:49 +00:00
moo_oop_t moo_allocoopobj ( moo_t * moo , moo_oow_t size )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_oop_t hdr ;
moo_oow_t nbytes , nbytes_aligned ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
nbytes = size * MOO_SIZEOF ( moo_oop_t ) ;
2015-04-30 15:56:05 +00:00
/* this isn't really necessary since nbytes must be
* aligned already . */
2017-01-09 09:54:49 +00:00
nbytes_aligned = MOO_ALIGN ( nbytes , MOO_SIZEOF ( moo_oop_t ) ) ;
2015-04-30 15:56:05 +00:00
/* making the number of bytes to allocate a multiple of
2017-01-09 09:54:49 +00:00
* MOO_SIZEOF ( moo_oop_t ) will guarantee the starting address
2015-04-30 15:56:05 +00:00
* of the allocated space to be an even number .
2017-01-09 09:54:49 +00:00
* see MOO_OOP_IS_NUMERIC ( ) and MOO_OOP_IS_POINTER ( ) */
2018-02-26 15:30:38 +00:00
hdr = ( moo_oop_oop_t ) moo_allocbytes ( moo , MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ) ;
2020-10-17 07:02:44 +00:00
if ( MOO_UNLIKELY ( ! hdr ) ) return MOO_NULL ;
2015-04-30 15:56:05 +00:00
2019-09-22 16:26:30 +00:00
hdr - > _flags = MOO_OBJ_MAKE_FLAGS ( MOO_OBJ_TYPE_OOP , MOO_SIZEOF ( moo_oop_t ) , 0 , 0 , moo - > igniting , 0 , 0 , 0 , 0 , 0 ) ;
2017-01-09 09:54:49 +00:00
MOO_OBJ_SET_SIZE ( hdr , size ) ;
MOO_OBJ_SET_CLASS ( hdr , moo - > _nil ) ;
2015-04-30 15:56:05 +00:00
2018-12-23 08:33:52 +00:00
while ( size > 0 )
{
size = size - 1 ;
MOO_OBJ_SET_OOP_VAL ( hdr , size , moo - > _nil ) ;
}
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
return ( moo_oop_t ) hdr ;
2015-04-30 15:56:05 +00:00
}
2017-01-09 09:54:49 +00:00
moo_oop_t moo_allocoopobjwithtrailer ( moo_t * moo , moo_oow_t size , const moo_oob_t * bptr , moo_oow_t blen )
2015-07-01 15:01:39 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_oop_t hdr ;
moo_oow_t nbytes , nbytes_aligned ;
moo_oow_t i ;
2015-07-01 15:01:39 +00:00
2017-01-09 09:54:49 +00:00
/* +1 for the trailer size of the moo_oow_t type */
nbytes = ( size + 1 ) * MOO_SIZEOF ( moo_oop_t ) + blen ;
nbytes_aligned = MOO_ALIGN ( nbytes , MOO_SIZEOF ( moo_oop_t ) ) ;
2015-07-01 15:01:39 +00:00
2018-02-26 15:30:38 +00:00
hdr = ( moo_oop_oop_t ) moo_allocbytes ( moo , MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ) ;
2020-10-26 16:43:09 +00:00
if ( MOO_UNLIKELY ( ! hdr ) ) return MOO_NULL ;
2015-07-01 15:01:39 +00:00
2019-09-22 16:26:30 +00:00
hdr - > _flags = MOO_OBJ_MAKE_FLAGS ( MOO_OBJ_TYPE_OOP , MOO_SIZEOF ( moo_oop_t ) , 0 , 0 , moo - > igniting , 0 , 0 , 1 , 0 , 1 ) ; /* TRAILER -> 1, UNCOPYABLE -> 1 */
2017-01-09 09:54:49 +00:00
MOO_OBJ_SET_SIZE ( hdr , size ) ;
MOO_OBJ_SET_CLASS ( hdr , moo - > _nil ) ;
2015-07-01 15:01:39 +00:00
2018-12-23 08:33:52 +00:00
for ( i = 0 ; i < size ; i + + )
{
MOO_OBJ_SET_OOP_VAL ( hdr , i , moo - > _nil ) ;
}
2015-07-01 15:01:39 +00:00
2018-12-16 17:35:46 +00:00
/* [NOTE] this is not converted to a SmallInteger object. it is a special slot handled by GC for an object with the TRAILER bit set */
2018-12-23 08:33:52 +00:00
MOO_OBJ_SET_OOP_VAL ( hdr , size , ( moo_oop_t ) blen ) ;
2015-07-01 15:01:39 +00:00
2018-12-23 08:33:52 +00:00
/* the trailer part is just composed of raw bytes from the moo core's perspective. */
2015-07-01 15:01:39 +00:00
if ( bptr )
{
2018-12-23 08:33:52 +00:00
MOO_MEMCPY ( ( moo_oob_t * ) MOO_OBJ_GET_OOP_PTR ( hdr , size + 1 ) , bptr , blen ) ;
2015-07-01 15:01:39 +00:00
}
else
{
2018-12-23 08:33:52 +00:00
MOO_MEMSET ( ( moo_oob_t * ) MOO_OBJ_GET_OOP_PTR ( hdr , size + 1 ) , 0 , blen ) ;
2015-07-01 15:01:39 +00:00
}
2017-01-09 09:54:49 +00:00
return ( moo_oop_t ) hdr ;
2015-07-01 15:01:39 +00:00
}
2018-12-29 15:16:58 +00:00
static MOO_INLINE moo_oop_t alloc_numeric_array ( moo_t * moo , const void * ptr , moo_oow_t len , moo_obj_type_t type , moo_oow_t unit , int extra )
2015-04-30 15:56:05 +00:00
{
/* allocate a variable object */
2017-01-09 09:54:49 +00:00
moo_oop_t hdr ;
moo_oow_t xbytes , nbytes , nbytes_aligned ;
2015-04-30 15:56:05 +00:00
2018-12-10 09:30:37 +00:00
xbytes = len * unit ;
2015-04-30 15:56:05 +00:00
/* 'extra' indicates an extra unit to append at the end.
* it ' s useful to store a string with a terminating null */
2018-12-10 09:30:37 +00:00
/*nbytes = extra? xbytes + len: xbytes; */
nbytes = extra ? xbytes + unit : xbytes ;
2017-01-09 09:54:49 +00:00
nbytes_aligned = MOO_ALIGN ( nbytes , MOO_SIZEOF ( moo_oop_t ) ) ;
2015-05-08 14:29:35 +00:00
/* TODO: check overflow in size calculation*/
2015-04-30 15:56:05 +00:00
2018-12-29 15:16:58 +00:00
/* making the number of bytes to allocate a multiple of
* MOO_SIZEOF ( moo_oop_t ) will guarantee the starting address
* of the allocated space to be an even number .
* see MOO_OOP_IS_NUMERIC ( ) and MOO_OOP_IS_POINTER ( ) */
hdr = ( moo_oop_t ) moo_allocbytes ( moo , MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ) ;
2020-10-26 16:43:09 +00:00
if ( MOO_UNLIKELY ( ! hdr ) ) return MOO_NULL ;
2015-04-30 15:56:05 +00:00
2019-09-22 16:26:30 +00:00
hdr - > _flags = MOO_OBJ_MAKE_FLAGS ( type , unit , extra , 0 , moo - > igniting , 0 , 0 , 0 , 0 , 0 ) ; /* TODO: review. ngc and perm flags seems to conflict with each other ... the diff is that ngc is malloc() and perm is allocated in the perm heap */
2015-05-03 17:10:30 +00:00
hdr - > _size = len ;
2017-01-09 09:54:49 +00:00
MOO_OBJ_SET_SIZE ( hdr , len ) ;
MOO_OBJ_SET_CLASS ( hdr , moo - > _nil ) ;
2015-04-30 15:56:05 +00:00
if ( ptr )
{
/* copy data */
2017-01-09 09:54:49 +00:00
MOO_MEMCPY ( hdr + 1 , ptr , xbytes ) ;
MOO_MEMSET ( ( moo_uint8_t * ) ( hdr + 1 ) + xbytes , 0 , nbytes_aligned - xbytes ) ;
2015-04-30 15:56:05 +00:00
}
else
{
2017-01-15 17:53:37 +00:00
/* initialize with zeros when the data pointer is NULL */
2017-01-09 09:54:49 +00:00
MOO_MEMSET ( ( hdr + 1 ) , 0 , nbytes_aligned ) ;
2015-04-30 15:56:05 +00:00
}
return hdr ;
}
2017-05-07 05:18:21 +00:00
MOO_INLINE moo_oop_t moo_alloccharobj ( moo_t * moo , const moo_ooch_t * ptr , moo_oow_t len )
2015-04-30 15:56:05 +00:00
{
2018-12-29 15:16:58 +00:00
return alloc_numeric_array ( moo , ptr , len , MOO_OBJ_TYPE_CHAR , MOO_SIZEOF ( moo_ooch_t ) , 1 ) ;
2015-04-30 15:56:05 +00:00
}
2017-05-07 05:18:21 +00:00
MOO_INLINE moo_oop_t moo_allocbyteobj ( moo_t * moo , const moo_oob_t * ptr , moo_oow_t len )
2015-07-01 15:01:39 +00:00
{
2018-12-29 15:16:58 +00:00
return alloc_numeric_array ( moo , ptr , len , MOO_OBJ_TYPE_BYTE , MOO_SIZEOF ( moo_oob_t ) , 0 ) ;
2015-07-01 15:01:39 +00:00
}
2017-05-07 05:18:21 +00:00
MOO_INLINE moo_oop_t moo_allochalfwordobj ( moo_t * moo , const moo_oohw_t * ptr , moo_oow_t len )
2015-04-30 15:56:05 +00:00
{
2018-12-29 15:16:58 +00:00
return alloc_numeric_array ( moo , ptr , len , MOO_OBJ_TYPE_HALFWORD , MOO_SIZEOF ( moo_oohw_t ) , 0 ) ;
2015-04-30 15:56:05 +00:00
}
2017-05-07 05:18:21 +00:00
MOO_INLINE moo_oop_t moo_allocwordobj ( moo_t * moo , const moo_oow_t * ptr , moo_oow_t len )
2015-04-30 15:56:05 +00:00
{
2018-12-29 15:16:58 +00:00
return alloc_numeric_array ( moo , ptr , len , MOO_OBJ_TYPE_WORD , MOO_SIZEOF ( moo_oow_t ) , 0 ) ;
2015-04-30 15:56:05 +00:00
}
2018-01-07 14:59:54 +00:00
static MOO_INLINE int decode_spec ( moo_t * moo , moo_oop_class_t _class , moo_oow_t num_flexi_fields , moo_obj_type_t * type , moo_oow_t * outlen )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oow_t spec ;
2018-01-07 14:59:54 +00:00
moo_oow_t num_fixed_fields ;
2017-01-09 09:54:49 +00:00
moo_obj_type_t indexed_type ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , MOO_OOP_IS_POINTER ( _class ) ) ;
MOO_ASSERT ( moo , MOO_CLASSOF ( moo , _class ) = = moo - > _class ) ;
2015-04-30 15:56:05 +00:00
2017-02-15 11:57:24 +00:00
MOO_ASSERT ( moo , MOO_OOP_IS_SMOOI ( _class - > spec ) ) ;
spec = MOO_OOP_TO_SMOOI ( _class - > spec ) ;
2015-04-30 15:56:05 +00:00
2018-01-07 14:59:54 +00:00
num_fixed_fields = MOO_CLASS_SPEC_NAMED_INSTVARS ( spec ) ;
MOO_ASSERT ( moo , num_fixed_fields < = MOO_MAX_NAMED_INSTVARS ) ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
if ( MOO_CLASS_SPEC_IS_INDEXED ( spec ) )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
indexed_type = MOO_CLASS_SPEC_INDEXED_TYPE ( spec ) ;
2015-05-03 17:10:30 +00:00
2018-01-07 14:59:54 +00:00
/* the number of the fixed fields for a non-pointer object are supported.
* the fixed fields of a pointer object holds named instance variables
* and a non - pointer object is facilitated with the fixed fields of the size
2018-01-06 04:18:10 +00:00
* specified in the class description like # byte ( 5 ) , # word ( 10 ) .
*
2018-01-07 14:59:54 +00:00
* when it comes to spec decoding , there is no difference between a pointer
2018-01-06 04:18:10 +00:00
* object and a non - pointer object */
2018-01-07 14:59:54 +00:00
if ( num_flexi_fields > MOO_MAX_INDEXED_INSTVARS ( num_fixed_fields ) )
2018-01-06 04:18:10 +00:00
{
2018-01-07 14:59:54 +00:00
moo_seterrbfmt ( moo , MOO_EINVAL , " number of flexi-fields(%zu) too big for a class %O " , num_flexi_fields , _class ) ;
2018-01-06 04:18:10 +00:00
return - 1 ;
}
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 */
2017-01-09 09:54:49 +00:00
indexed_type = MOO_OBJ_TYPE_OOP ;
2015-05-03 17:10:30 +00:00
2018-01-07 14:59:54 +00:00
if ( num_flexi_fields > 0 )
2016-11-18 18:11:13 +00:00
{
2018-05-13 16:28:22 +00:00
moo_seterrbfmt ( moo , MOO_EPERM , " flexi-fields(%zu) disallowed for a class %O " , num_flexi_fields , _class ) ;
2016-11-18 18:11:13 +00:00
return - 1 ;
}
2015-04-30 15:56:05 +00:00
}
2018-01-07 14:59:54 +00:00
MOO_ASSERT ( moo , num_fixed_fields + num_flexi_fields < = MOO_OBJ_SIZE_MAX ) ;
2015-12-27 18:02:59 +00:00
* type = indexed_type ;
2018-01-07 14:59:54 +00:00
* outlen = num_fixed_fields + num_flexi_fields ;
2015-12-27 18:02:59 +00:00
return 0 ;
}
2017-02-15 11:57:24 +00:00
moo_oop_t moo_instantiate ( moo_t * moo , moo_oop_class_t _class , const void * vptr , moo_oow_t vlen )
2015-12-27 18:02:59 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_t oop ;
moo_obj_type_t type ;
moo_oow_t alloclen ;
moo_oow_t tmp_count = 0 ;
2015-12-27 18:02:59 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , moo - > _nil ! = MOO_NULL ) ;
2015-12-27 18:02:59 +00:00
2018-01-05 17:46:10 +00:00
if ( decode_spec ( moo , _class , vlen , & type , & alloclen ) < = - 1 ) return MOO_NULL ;
2015-12-27 18:02:59 +00:00
2018-12-28 08:29:27 +00:00
moo_pushvolat ( moo , ( moo_oop_t * ) & _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
{
2017-01-09 09:54:49 +00:00
case MOO_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 . */
2018-02-26 15:30:38 +00:00
oop = moo_allocoopobj ( moo , alloclen ) ;
2017-04-19 16:46:44 +00:00
if ( oop )
{
/* initialize named instance variables with default values */
2017-04-24 14:32:21 +00:00
if ( _class - > initv [ 0 ] ! = moo - > _nil )
2017-04-19 16:46:44 +00:00
{
2017-04-24 14:32:21 +00:00
moo_oow_t i = MOO_OBJ_GET_SIZE ( _class - > initv [ 0 ] ) ;
2017-04-19 16:46:44 +00:00
2017-04-24 04:26:03 +00:00
/* [NOTE] i don't deep-copy initial values.
* if you change the contents of compound values like arrays ,
* it affects subsequent instantiation of the class .
* it ' s important that the compiler should mark compound initial
* values read - only . */
2017-04-19 16:46:44 +00:00
while ( i > 0 )
{
- - i ;
2018-12-23 08:33:52 +00:00
MOO_STORE_OOP ( moo , MOO_OBJ_GET_OOP_PTR ( oop , i ) , MOO_OBJ_GET_OOP_VAL ( _class - > initv [ 0 ] , i ) ) ;
2017-04-19 16:46:44 +00:00
}
}
}
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , vptr = = MOO_NULL ) ;
2015-06-03 17:24:11 +00:00
/*
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
{
2017-01-09 09:54:49 +00:00
moo_oop_oop_t hdr = ( moo_oop_oop_t ) oop ;
MOO_MEMCPY ( & hdr - > slot [ named_instvar ] , vptr , vlen * MOO_SIZEOF ( moo_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
2018-12-28 08:29:27 +00:00
the vptr array with moo_pushvolat ( ) . So it might be better
2015-12-02 15:24:13 +00:00
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 ;
2017-01-09 09:54:49 +00:00
case MOO_OBJ_TYPE_CHAR :
2018-02-26 15:30:38 +00:00
oop = moo_alloccharobj ( moo , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
2017-01-09 09:54:49 +00:00
case MOO_OBJ_TYPE_BYTE :
2018-02-26 15:30:38 +00:00
oop = moo_allocbyteobj ( moo , vptr , alloclen ) ;
2015-10-30 15:36:37 +00:00
break ;
2017-01-09 09:54:49 +00:00
case MOO_OBJ_TYPE_HALFWORD :
2018-02-26 15:30:38 +00:00
oop = moo_allochalfwordobj ( moo , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
2017-01-09 09:54:49 +00:00
case MOO_OBJ_TYPE_WORD :
2018-02-26 15:30:38 +00:00
oop = moo_allocwordobj ( moo , vptr , alloclen ) ;
2015-04-30 15:56:05 +00:00
break ;
default :
2017-05-11 14:59:20 +00:00
moo_seterrnum ( moo , MOO_EINTERN ) ;
2017-01-09 09:54:49 +00:00
oop = MOO_NULL ;
2015-05-08 14:29:35 +00:00
break ;
2015-04-30 15:56:05 +00:00
}
2017-05-07 05:18:21 +00:00
if ( oop )
2015-07-01 15:01:39 +00:00
{
2019-09-22 15:59:09 +00:00
moo_ooi_t spec ;
2017-05-07 05:18:21 +00:00
MOO_OBJ_SET_CLASS ( oop , ( moo_oop_t ) _class ) ;
2019-09-22 15:59:09 +00:00
spec = MOO_OOP_TO_SMOOI ( _class - > spec ) ;
if ( MOO_CLASS_SPEC_IS_IMMUTABLE ( spec ) ) MOO_OBJ_SET_FLAGS_RDONLY ( oop , 1 ) ;
if ( MOO_CLASS_SPEC_IS_UNCOPYABLE ( spec ) ) MOO_OBJ_SET_FLAGS_UNCOPYABLE ( oop , 1 ) ;
2015-07-01 15:01:39 +00:00
}
2018-12-28 08:29:27 +00:00
moo_popvolats ( moo , tmp_count ) ;
2015-12-27 18:02:59 +00:00
return oop ;
}
2017-02-15 11:57:24 +00:00
moo_oop_t moo_instantiatewithtrailer ( moo_t * moo , moo_oop_class_t _class , moo_oow_t vlen , const moo_oob_t * trptr , moo_oow_t trlen )
2015-12-27 18:02:59 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_t oop ;
moo_obj_type_t type ;
moo_oow_t alloclen ;
moo_oow_t tmp_count = 0 ;
2015-12-27 18:02:59 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , moo - > _nil ! = MOO_NULL ) ;
2015-12-27 18:02:59 +00:00
2018-01-05 17:46:10 +00:00
if ( decode_spec ( moo , _class , vlen , & type , & alloclen ) < = - 1 ) return MOO_NULL ;
2015-07-01 15:01:39 +00:00
2018-12-28 08:29:27 +00:00
moo_pushvolat ( moo , ( moo_oop_t * ) & _class ) ; tmp_count + + ;
2015-07-01 15:01:39 +00:00
2015-12-27 18:02:59 +00:00
switch ( type )
2015-07-01 15:01:39 +00:00
{
2017-01-09 09:54:49 +00:00
case MOO_OBJ_TYPE_OOP :
2017-02-14 10:25:26 +00:00
oop = moo_allocoopobjwithtrailer ( moo , alloclen , trptr , trlen ) ;
2017-05-07 05:18:21 +00:00
if ( oop )
{
/* initialize named instance variables with default values */
if ( _class - > initv [ 0 ] ! = moo - > _nil )
{
moo_oow_t i = MOO_OBJ_GET_SIZE ( _class - > initv [ 0 ] ) ;
/* [NOTE] i don't deep-copy initial values.
* if you change the contents of compound values like arrays ,
* it affects subsequent instantiation of the class .
* it ' s important that the compiler should mark compound initial
* values read - only . */
while ( i > 0 )
{
- - i ;
2018-12-23 08:33:52 +00:00
MOO_STORE_OOP ( moo , MOO_OBJ_GET_OOP_PTR ( oop , i ) , MOO_OBJ_GET_OOP_VAL ( _class - > initv [ 0 ] , i ) ) ;
2017-05-07 05:18:21 +00:00
}
}
}
2015-07-01 15:01:39 +00:00
break ;
default :
2017-02-14 08:29:30 +00:00
MOO_DEBUG3 ( moo , " Not allowed to instantiate a non-pointer object of the %.*js class with trailer %zu \n " ,
2017-02-15 11:57:24 +00:00
MOO_OBJ_GET_SIZE ( _class - > name ) ,
MOO_OBJ_GET_CHAR_SLOT ( _class - > name ) ,
2017-02-14 10:25:26 +00:00
trlen ) ;
2017-02-14 08:29:30 +00:00
2017-05-11 14:59:20 +00:00
moo_seterrnum ( moo , MOO_EPERM ) ;
2017-01-09 09:54:49 +00:00
oop = MOO_NULL ;
2015-07-01 15:01:39 +00:00
break ;
}
2017-05-07 05:18:21 +00:00
if ( oop )
{
2019-09-22 15:59:09 +00:00
moo_ooi_t spec ;
2017-05-07 05:18:21 +00:00
MOO_OBJ_SET_CLASS ( oop , _class ) ;
2019-09-22 15:59:09 +00:00
spec = MOO_OOP_TO_SMOOI ( _class - > spec ) ;
if ( MOO_CLASS_SPEC_IS_IMMUTABLE ( spec ) ) MOO_OBJ_SET_FLAGS_RDONLY ( oop , 1 ) ;
2019-09-22 16:26:30 +00:00
/* the object with trailer is to to uncopyable in moo_allocoopobjwithtrailer() so no need to check/set it again here
if ( MOO_CLASS_SPEC_IS_UNCOPYABLE ( spec ) ) MOO_OBJ_SET_FLAGS_UNCOPYABLE ( oop , 1 ) ;
*/
2017-05-07 05:18:21 +00:00
}
2019-09-22 15:59:09 +00:00
2018-12-28 08:29:27 +00:00
moo_popvolats ( moo , tmp_count ) ;
2015-07-01 15:01:39 +00:00
return oop ;
}
2019-09-06 03:33:34 +00:00
moo_oop_t moo_oowtoptr ( moo_t * moo , moo_oow_t num )
{
moo_oop_t ret ;
if ( MOO_IN_SMPTR_RANGE ( num ) ) return MOO_SMPTR_TO_OOP ( num ) ;
ret = moo_instantiate ( moo , moo - > _large_pointer , MOO_NULL , 0 ) ;
if ( ! ret ) return MOO_NULL ;
MOO_OBJ_SET_WORD_VAL ( ret , 0 , num ) ;
return ret ;
}
int moo_ptrtooow ( moo_t * moo , moo_oop_t ptr , moo_oow_t * num )
{
if ( MOO_OOP_IS_SMPTR ( ptr ) )
{
* num = ( moo_oow_t ) MOO_OOP_TO_SMPTR ( ptr ) ;
return 0 ;
}
if ( MOO_CLASSOF ( moo , ptr ) = = moo - > _large_pointer )
{
MOO_ASSERT ( moo , MOO_OBJ_GET_SIZE ( ptr ) = = 1 ) ;
* num = MOO_OBJ_GET_WORD_VAL ( ptr , 0 ) ;
return 0 ;
}
moo_seterrnum ( moo , MOO_EINVAL ) ;
return - 1 ;
}