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
2016-12-26 18:44:47 +00:00
/*
2017-11-03 16:26:55 +00:00
* Apex . . . . . . . . . . . . . . . . . . . . . .
2016-12-26 18:44:47 +00:00
* ^ ^ ^ : . . . . . . .
* | | | v v :
* | | + - - - - - - - - - - - - - - - - - - - Class . . . . .
* | | ^ ^
* | + - - - - - - - - NilObject . . . . . . : :
* | ^ . . . . . . . . nil :
* Object . . . . . . . . . . . . . . . . . . . . . . . . . . . :
* ^
* |
*
* The class hierarchy is roughly as follows :
*
2017-11-03 16:26:55 +00:00
* Apex
2016-12-26 18:44:47 +00:00
* Class
* NilObject
* Object
* Collection
* IndexedCollection
* FixedSizedCollection
* Array
* ByteArray
* String
* Symbol
* Set
* Dictionary
* SystemDictionary
* SymbolSet
* Magnitude
* Association
* Character
* Number
* Integer
* SmallInteger
* LargeInteger
* LargePositiveInteger
* LargeNegativeInteger
*
2017-11-03 16:26:55 +00:00
* Apex has no instance variables .
2016-12-26 18:44:47 +00:00
*
*/
struct kernel_class_info_t
{
2017-01-09 09:54:49 +00:00
moo_oow_t len ;
moo_ooch_t name [ 20 ] ;
2017-08-22 13:45:37 +00:00
int class_flags ;
2017-10-31 07:13:22 +00:00
int class_num_classvars ;
2017-08-22 13:45:37 +00:00
int class_spec_named_instvars ;
int class_spec_flags ;
int class_spec_indexed_type ;
2017-01-09 09:54:49 +00:00
moo_oow_t offset ;
2016-12-26 18:44:47 +00:00
} ;
typedef struct kernel_class_info_t kernel_class_info_t ;
static kernel_class_info_t kernel_classes [ ] =
{
2017-08-22 13:45:37 +00:00
/* --------------------------------------------------------------
* Apex - proto - object with 1 class variable .
* UndefinedObject - class for the nil object .
* Object - top of all ordinary objects .
* String
* Symbol
* Array
* ByteArray
* SymbolSet
* Character
* SmallIntger
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
{ 4 ,
{ ' A ' , ' p ' , ' e ' , ' x ' } ,
0 ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _apex ) } ,
{ 15 ,
{ ' U ' , ' n ' , ' d ' , ' e ' , ' f ' , ' i ' , ' n ' , ' e ' , ' d ' , ' O ' , ' b ' , ' j ' , ' e ' , ' c ' , ' t ' } ,
0 ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _undefined_object ) } ,
2017-10-31 07:13:22 +00:00
# define KCI_CLASS 2 /* index to the Class entry in this table */
2017-08-22 13:45:37 +00:00
{ 5 ,
{ ' C ' , ' l ' , ' a ' , ' s ' , ' s ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _class ) } ,
2018-07-08 17:13:10 +00:00
{ 9 ,
{ ' I ' , ' n ' , ' t ' , ' e ' , ' r ' , ' f ' , ' a ' , ' c ' , ' e ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
2018-10-09 15:21:58 +00:00
MOO_INTERFACE_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2018-07-08 17:13:10 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _interface ) } ,
2017-08-22 13:45:37 +00:00
{ 6 ,
{ ' O ' , ' b ' , ' j ' , ' e ' , ' c ' , ' t ' } ,
0 ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _object ) } ,
{ 6 ,
{ ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' } ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_CHAR ,
MOO_OFFSETOF ( moo_t , _string ) } ,
{ 6 ,
{ ' S ' , ' y ' , ' m ' , ' b ' , ' o ' , ' l ' } ,
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE ,
MOO_OBJ_TYPE_CHAR ,
MOO_OFFSETOF ( moo_t , _symbol ) } ,
{ 5 ,
{ ' A ' , ' r ' , ' r ' , ' a ' , ' y ' } ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _array ) } ,
{ 9 ,
{ ' B ' , ' y ' , ' t ' , ' e ' , ' A ' , ' r ' , ' r ' , ' a ' , ' y ' } ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_BYTE ,
MOO_OFFSETOF ( moo_t , _byte_array ) } ,
2018-06-20 18:01:04 +00:00
{ 11 ,
{ ' S ' , ' y ' , ' m ' , ' b ' , ' o ' , ' l ' , ' T ' , ' a ' , ' b ' , ' l ' , ' e ' } ,
2017-08-22 13:45:37 +00:00
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_DIC_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
2018-06-20 18:01:04 +00:00
MOO_OFFSETOF ( moo_t , _symbol_table ) } ,
2017-08-22 13:45:37 +00:00
{ 10 ,
{ ' D ' , ' i ' , ' c ' , ' t ' , ' i ' , ' o ' , ' n ' , ' a ' , ' r ' , ' y ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_DIC_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _dictionary ) } ,
2018-10-10 04:23:44 +00:00
{ 11 ,
{ ' A ' , ' s ' , ' s ' , ' o ' , ' c ' , ' i ' , ' a ' , ' t ' , ' i ' , ' o ' , ' n ' } ,
0 ,
0 ,
MOO_ASSOCIATION_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _association ) } ,
2017-08-22 13:45:37 +00:00
{ 9 ,
{ ' N ' , ' a ' , ' m ' , ' e ' , ' s ' , ' p ' , ' a ' , ' c ' , ' e ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_NSDIC_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _namespace ) } ,
{ 14 ,
{ ' P ' , ' o ' , ' o ' , ' l ' , ' D ' , ' i ' , ' c ' , ' t ' , ' i ' , ' o ' , ' n ' , ' a ' , ' r ' , ' y ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_DIC_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _pool_dictionary ) } ,
{ 16 ,
{ ' M ' , ' e ' , ' t ' , ' h ' , ' o ' , ' d ' , ' D ' , ' i ' , ' c ' , ' t ' , ' i ' , ' o ' , ' n ' , ' a ' , ' r ' , ' y ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_DIC_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _method_dictionary ) } ,
{ 14 ,
{ ' C ' , ' o ' , ' m ' , ' p ' , ' i ' , ' l ' , ' e ' , ' d ' , ' M ' , ' e ' , ' t ' , ' h ' , ' o ' , ' d ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_METHOD_NAMED_INSTVARS ,
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _method ) } ,
2018-10-10 04:23:44 +00:00
{ 15 ,
{ ' M ' , ' e ' , ' t ' , ' h ' , ' o ' , ' d ' , ' S ' , ' i ' , ' g ' , ' n ' , ' a ' , ' t ' , ' u ' , ' r ' , ' e ' } ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
0 ,
2018-10-10 04:23:44 +00:00
MOO_METHSIG_NAMED_INSTVARS ,
MOO_CLASS_SPEC_FLAG_INDEXED ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
2018-10-10 04:23:44 +00:00
MOO_OFFSETOF ( moo_t , _methsig ) } ,
2020-10-15 14:50:08 +00:00
{ 13 ,
{ ' C ' , ' o ' , ' m ' , ' p ' , ' i ' , ' l ' , ' e ' , ' d ' , ' B ' , ' l ' , ' o ' , ' c ' , ' k ' } ,
0 ,
0 ,
MOO_BLOCK_NAMED_INSTVARS ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _block ) } ,
2017-08-22 13:45:37 +00:00
{ 13 ,
{ ' M ' , ' e ' , ' t ' , ' h ' , ' o ' , ' d ' , ' C ' , ' o ' , ' n ' , ' t ' , ' e ' , ' x ' , ' t ' } ,
2017-09-29 15:03:54 +00:00
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CONTEXT_NAMED_INSTVARS ,
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _method_context ) } ,
{ 12 ,
{ ' B ' , ' l ' , ' o ' , ' c ' , ' k ' , ' C ' , ' o ' , ' n ' , ' t ' , ' e ' , ' x ' , ' t ' } ,
2017-09-29 15:03:54 +00:00
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CONTEXT_NAMED_INSTVARS ,
MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _block_context ) } ,
{ 7 ,
{ ' P ' , ' r ' , ' o ' , ' c ' , ' e ' , ' s ' , ' s ' } ,
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_PROCESS_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _process ) } ,
{ 9 ,
{ ' S ' , ' e ' , ' m ' , ' a ' , ' p ' , ' h ' , ' o ' , ' r ' , ' e ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_SEMAPHORE_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _semaphore ) } ,
{ 14 ,
{ ' S ' , ' e ' , ' m ' , ' a ' , ' p ' , ' h ' , ' o ' , ' r ' , ' e ' , ' G ' , ' r ' , ' o ' , ' u ' , ' p ' } ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_SEMAPHORE_GROUP_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _semaphore_group ) } ,
{ 16 ,
{ ' P ' , ' r ' , ' o ' , ' c ' , ' e ' , ' s ' , ' s ' , ' S ' , ' c ' , ' h ' , ' e ' , ' d ' , ' u ' , ' l ' , ' e ' , ' r ' } ,
2017-10-31 07:13:22 +00:00
MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
MOO_PROCESS_SCHEDULER_NAMED_INSTVARS ,
2019-09-22 15:59:09 +00:00
MOO_CLASS_SPEC_FLAG_UNCOPYABLE ,
2017-10-31 07:13:22 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _process_scheduler ) } ,
2017-08-22 13:45:37 +00:00
{ 5 ,
{ ' E ' , ' r ' , ' r ' , ' o ' , ' r ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _error_class ) } ,
{ 4 ,
{ ' T ' , ' r ' , ' u ' , ' e ' } ,
2019-10-21 14:42:01 +00:00
MOO_CLASS_SELFSPEC_FLAG_LIMITED | MOO_CLASS_SELFSPEC_FLAG_FINAL ,
2017-08-22 13:45:37 +00:00
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _true_class ) } ,
{ 5 ,
{ ' F ' , ' a ' , ' l ' , ' s ' , ' e ' } ,
2019-10-21 14:42:01 +00:00
MOO_CLASS_SELFSPEC_FLAG_LIMITED | MOO_CLASS_SELFSPEC_FLAG_FINAL ,
2017-08-22 13:45:37 +00:00
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _false_class ) } ,
/* TOOD: what is a proper spec for Character and SmallInteger?
* If the fixed part is 0 , its instance must be an object of 0 payload fields .
* Does this make sense ? */
{ 9 ,
{ ' C ' , ' h ' , ' a ' , ' r ' , ' a ' , ' c ' , ' t ' , ' e ' , ' r ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _character ) } ,
{ 12 ,
{ ' S ' , ' m ' , ' a ' , ' l ' , ' l ' , ' I ' , ' n ' , ' t ' , ' e ' , ' g ' , ' e ' , ' r ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _small_integer ) } ,
{ 20 ,
{ ' L ' , ' a ' , ' r ' , ' g ' , ' e ' , ' P ' , ' o ' , ' s ' , ' i ' , ' t ' , ' i ' , ' v ' , ' e ' , ' I ' , ' n ' , ' t ' , ' e ' , ' g ' , ' e ' , ' r ' } ,
2019-01-01 06:44:28 +00:00
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-08-22 13:45:37 +00:00
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE ,
MOO_OBJ_TYPE_LIWORD ,
MOO_OFFSETOF ( moo_t , _large_positive_integer ) } ,
{ 20 ,
{ ' L ' , ' a ' , ' r ' , ' g ' , ' e ' , ' N ' , ' e ' , ' g ' , ' a ' , ' t ' , ' i ' , ' v ' , ' e ' , ' I ' , ' n ' , ' t ' , ' e ' , ' g ' , ' e ' , ' r ' } ,
2019-01-01 06:44:28 +00:00
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-08-22 13:45:37 +00:00
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE ,
MOO_OBJ_TYPE_LIWORD ,
MOO_OFFSETOF ( moo_t , _large_negative_integer ) } ,
2018-12-20 16:33:23 +00:00
{ 17 ,
{ ' F ' , ' i ' , ' x ' , ' e ' , ' d ' , ' P ' , ' o ' , ' i ' , ' n ' , ' t ' , ' D ' , ' e ' , ' c ' , ' i ' , ' m ' , ' a ' , ' l ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
MOO_FPDEC_NAMED_INSTVARS ,
2019-01-01 06:44:28 +00:00
MOO_CLASS_SPEC_FLAG_IMMUTABLE ,
2018-12-20 16:33:23 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _fixed_point_decimal ) } ,
2017-08-22 13:45:37 +00:00
{ 12 ,
{ ' S ' , ' m ' , ' a ' , ' l ' , ' l ' , ' P ' , ' o ' , ' i ' , ' n ' , ' t ' , ' e ' , ' r ' } ,
2019-09-05 15:55:39 +00:00
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
2017-08-22 13:45:37 +00:00
0 ,
0 ,
2017-10-31 07:13:22 +00:00
0 ,
2017-08-22 13:45:37 +00:00
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _small_pointer ) } ,
2019-09-05 15:55:39 +00:00
{ 12 ,
{ ' L ' , ' a ' , ' r ' , ' g ' , ' e ' , ' P ' , ' o ' , ' i ' , ' n ' , ' t ' , ' e ' , ' r ' } ,
MOO_CLASS_SELFSPEC_FLAG_LIMITED ,
0 ,
1 , /* #word(1) */
MOO_CLASS_SPEC_FLAG_IMMUTABLE | MOO_CLASS_SPEC_FLAG_INDEXED ,
MOO_OBJ_TYPE_WORD ,
MOO_OFFSETOF ( moo_t , _large_pointer ) } ,
2017-08-22 13:45:37 +00:00
{ 6 ,
{ ' S ' , ' y ' , ' s ' , ' t ' , ' e ' , ' m ' } ,
0 ,
2019-11-04 14:53:33 +00:00
5 , /* asyncsg, gcfin_sem, gcfin_should_exit, ossig_pid, shr */
2017-08-22 13:45:37 +00:00
0 ,
0 ,
MOO_OBJ_TYPE_OOP ,
MOO_OFFSETOF ( moo_t , _system ) }
2016-12-26 18:44:47 +00:00
} ;
2017-07-20 16:33:53 +00:00
2017-07-27 08:32:16 +00:00
static moo_oow_t move_finalizable_objects ( moo_t * moo ) ;
2017-07-20 16:33:53 +00:00
2016-12-26 18:44:47 +00:00
/* -----------------------------------------------------------------------
* BOOTSTRAPPER
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-05-01 12:54:41 +00:00
static moo_oop_class_t alloc_kernel_class ( moo_t * moo , int class_flags , moo_oow_t num_classvars , moo_oow_t spec )
2016-12-26 18:44:47 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_class_t c ;
2019-09-22 15:59:09 +00:00
moo_ooi_t cspec ;
2016-12-26 18:44:47 +00:00
2018-12-08 17:36:20 +00:00
c = ( moo_oop_class_t ) moo_allocoopobj ( moo , MOO_CLASS_NAMED_INSTVARS + num_classvars ) ;
2017-01-09 09:54:49 +00:00
if ( ! c ) return MOO_NULL ;
2016-12-26 18:44:47 +00:00
2018-10-12 09:09:45 +00:00
MOO_OBJ_SET_FLAGS_KERNEL ( c , MOO_OBJ_FLAGS_KERNEL_IMMATURE ) ;
2019-09-22 15:59:09 +00:00
cspec = kernel_classes [ KCI_CLASS ] . class_spec_flags ;
if ( MOO_CLASS_SPEC_IS_IMMUTABLE ( cspec ) ) MOO_OBJ_SET_FLAGS_RDONLY ( c , 1 ) ; /* just for completeness of code. will never be true as it's not defined in the kernel class info table */
if ( MOO_CLASS_SPEC_IS_UNCOPYABLE ( cspec ) ) MOO_OBJ_SET_FLAGS_UNCOPYABLE ( c , 1 ) ; /* class itself is uncopyable */
2017-02-15 11:57:24 +00:00
MOO_OBJ_SET_CLASS ( c , ( moo_oop_t ) moo - > _class ) ;
2017-01-09 09:54:49 +00:00
c - > spec = MOO_SMOOI_TO_OOP ( spec ) ;
2017-05-01 12:54:41 +00:00
c - > selfspec = MOO_SMOOI_TO_OOP ( MOO_CLASS_SELFSPEC_MAKE ( num_classvars , 0 , class_flags ) ) ;
2016-12-26 18:44:47 +00:00
2017-02-15 11:57:24 +00:00
return c ;
2016-12-26 18:44:47 +00:00
}
2017-01-09 09:54:49 +00:00
static int ignite_1 ( moo_t * moo )
2016-12-26 18:44:47 +00:00
{
2017-08-22 13:45:37 +00:00
moo_oow_t i ;
2016-12-26 18:44:47 +00:00
/*
* Create fundamental class objects with some fields mis - initialized yet .
* Such fields include ' superclass ' , ' subclasses ' , ' name ' , etc .
*/
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , moo - > _nil ! = MOO_NULL ) ;
MOO_ASSERT ( moo , MOO_OBJ_GET_CLASS ( moo - > _nil ) = = MOO_NULL ) ;
2016-12-26 18:44:47 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , moo - > _class = = MOO_NULL ) ;
2016-12-26 18:44:47 +00:00
/* --------------------------------------------------------------
* Class
* The instance of Class can have indexed instance variables
* which are actually class variables .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2018-12-08 17:36:20 +00:00
moo - > _class = alloc_kernel_class (
2017-10-31 07:13:22 +00:00
moo , kernel_classes [ KCI_CLASS ] . class_flags ,
kernel_classes [ KCI_CLASS ] . class_num_classvars ,
2018-12-08 17:36:20 +00:00
MOO_CLASS_SPEC_MAKE ( kernel_classes [ KCI_CLASS ] . class_spec_named_instvars ,
kernel_classes [ KCI_CLASS ] . class_spec_flags ,
kernel_classes [ KCI_CLASS ] . class_spec_indexed_type ) ) ;
2017-01-09 09:54:49 +00:00
if ( ! moo - > _class ) return - 1 ;
2016-12-26 18:44:47 +00:00
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , MOO_OBJ_GET_CLASS ( moo - > _class ) = = MOO_NULL ) ;
2017-02-15 11:57:24 +00:00
MOO_OBJ_SET_CLASS ( moo - > _class , ( moo_oop_t ) moo - > _class ) ;
2016-12-26 18:44:47 +00:00
2017-08-22 13:45:37 +00:00
for ( i = 0 ; i < MOO_COUNTOF ( kernel_classes ) ; i + + )
{
moo_oop_class_t tmp ;
2016-12-26 18:44:47 +00:00
2017-08-22 13:45:37 +00:00
if ( i = = KCI_CLASS ) continue ; /* skip Class as it's created above */
2016-12-26 18:44:47 +00:00
2018-12-08 17:36:20 +00:00
tmp = alloc_kernel_class (
2017-10-31 07:13:22 +00:00
moo , kernel_classes [ i ] . class_flags ,
kernel_classes [ i ] . class_num_classvars ,
2018-12-08 17:36:20 +00:00
MOO_CLASS_SPEC_MAKE ( kernel_classes [ i ] . class_spec_named_instvars ,
kernel_classes [ i ] . class_spec_flags ,
kernel_classes [ i ] . class_spec_indexed_type ) ) ;
2017-08-22 13:45:37 +00:00
if ( ! tmp ) return - 1 ;
* ( moo_oop_class_t * ) ( ( moo_uint8_t * ) moo + kernel_classes [ i ] . offset ) = tmp ;
}
2016-12-26 18:44:47 +00:00
2017-02-15 11:57:24 +00:00
MOO_OBJ_SET_CLASS ( moo - > _nil , ( moo_oop_t ) moo - > _undefined_object ) ;
2017-06-16 09:45:22 +00:00
2019-10-04 18:32:38 +00:00
/* an instance of a method class stores byte codes in the trailer space.
* unlike other classes with trailer size set , the size of the trailer
* space is not really determined by the traailer size set in the class .
* the compiler determines the actual size of the trailer space depending
* on the byte codes generated . i should set the following fields to avoid
* confusion at the GC phase . */
2017-06-16 09:45:22 +00:00
moo - > _method - > trsize = MOO_SMOOI_TO_OOP ( 0 ) ;
moo - > _method - > trgc = MOO_SMPTR_TO_OOP ( 0 ) ;
2016-12-26 18:44:47 +00:00
return 0 ;
}
2017-01-09 09:54:49 +00:00
static int ignite_2 ( moo_t * moo )
2016-12-26 18:44:47 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_t tmp ;
2018-12-31 16:47:54 +00:00
int old_igniting = moo - > igniting ;
2016-12-26 18:44:47 +00:00
/* Create 'true' and 'false objects */
2018-12-08 15:35:26 +00:00
moo - > _true = moo_instantiate ( moo , moo - > _true_class , MOO_NULL , 0 ) ;
moo - > _false = moo_instantiate ( moo , moo - > _false_class , MOO_NULL , 0 ) ;
2020-10-17 07:02:44 +00:00
if ( MOO_UNLIKELY ( ! moo - > _true ) | | MOO_UNLIKELY ( ! moo - > _false ) ) return - 1 ;
2016-12-26 18:44:47 +00:00
2018-12-31 16:47:54 +00:00
/* Prevent the object instations in the permspace.
*
* 1. The symbol table is big and it may resize after ignition .
* the resizing operation will migrate the obejct out of the
* permspace . The space taken by the symbol table and the
* system dictionary is wasted . I ' d rather allocate these
* in the normal space .
*
* 2. For compact_symbol_table ( ) to work properly , moo_gc ( ) must not
* scan the symbol table before it executes compact_symbol_table ( ) .
* since moo_gc ( ) scans the entire perspace , it naturally gets to
* moo - > symtab , which causes problems in compact_symbol_table ( ) .
* I may reserve a special space for only the symbol table
* to overcome this issue .
*
* For now , let ' s just allocate the symbol table and the system dictionary
* in the normal space */
moo - > igniting = 0 ;
2016-12-26 18:44:47 +00:00
/* Create the symbol table */
2018-12-08 15:35:26 +00:00
tmp = moo_instantiate ( moo , moo - > _symbol_table , MOO_NULL , 0 ) ;
2020-10-17 07:02:44 +00:00
if ( MOO_UNLIKELY ( ! tmp ) ) return - 1 ;
2017-05-20 02:27:48 +00:00
moo - > symtab = ( moo_oop_dic_t ) tmp ;
2016-12-26 18:44:47 +00:00
2017-01-09 09:54:49 +00:00
moo - > symtab - > tally = MOO_SMOOI_TO_OOP ( 0 ) ;
/* It's important to assign the result of moo_instantiate() to a temporary
* variable first and then assign it to moo - > symtab - > bucket .
* The pointer ' moo - > symtab ; can change in moo_instantiate ( ) and the
* target address of assignment may get set before moo_instantiate ( )
2016-12-26 18:44:47 +00:00
* is called . */
2018-06-20 18:01:04 +00:00
tmp = moo_instantiate ( moo , moo - > _array , MOO_NULL , moo - > option . dfl_symtab_size ) ;
2016-12-26 18:44:47 +00:00
if ( ! tmp ) return - 1 ;
2017-01-09 09:54:49 +00:00
moo - > symtab - > bucket = ( moo_oop_oop_t ) tmp ;
2016-12-26 18:44:47 +00:00
/* Create the system dictionary */
2018-06-20 18:01:04 +00:00
tmp = ( moo_oop_t ) moo_makensdic ( moo , moo - > _namespace , moo - > option . dfl_sysdic_size ) ;
2016-12-26 18:44:47 +00:00
if ( ! tmp ) return - 1 ;
2017-05-20 02:27:48 +00:00
moo - > sysdic = ( moo_oop_nsdic_t ) tmp ;
2016-12-26 18:44:47 +00:00
2018-12-31 16:47:54 +00:00
moo - > igniting = old_igniting ; /* back to the permspace */
2016-12-26 18:44:47 +00:00
/* Create a nil process used to simplify nil check in GC.
* only accessible by VM . not exported via the global dictionary . */
2018-06-20 18:01:04 +00:00
tmp = ( moo_oop_t ) moo_instantiate ( moo , moo - > _process , MOO_NULL , 0 ) ;
2016-12-26 18:44:47 +00:00
if ( ! tmp ) return - 1 ;
2017-01-09 09:54:49 +00:00
moo - > nil_process = ( moo_oop_process_t ) tmp ;
moo - > nil_process - > sp = MOO_SMOOI_TO_OOP ( - 1 ) ;
2017-09-25 15:16:19 +00:00
moo - > nil_process - > id = MOO_SMOOI_TO_OOP ( - 1 ) ;
moo - > nil_process - > perr = MOO_ERROR_TO_OOP ( MOO_ENOERR ) ;
moo - > nil_process - > perrmsg = moo - > _nil ;
2016-12-26 18:44:47 +00:00
/* Create a process scheduler */
2018-12-08 15:35:26 +00:00
tmp = ( moo_oop_t ) moo_instantiate ( moo , moo - > _process_scheduler , MOO_NULL , 0 ) ;
2016-12-26 18:44:47 +00:00
if ( ! tmp ) return - 1 ;
2017-01-09 09:54:49 +00:00
moo - > processor = ( moo_oop_process_scheduler_t ) tmp ;
moo - > processor - > active = moo - > nil_process ;
2017-07-25 15:26:04 +00:00
moo - > processor - > total_count = MOO_SMOOI_TO_OOP ( 0 ) ;
2017-07-24 13:25:25 +00:00
moo - > processor - > runnable . count = MOO_SMOOI_TO_OOP ( 0 ) ;
moo - > processor - > suspended . count = MOO_SMOOI_TO_OOP ( 0 ) ;
2016-12-26 18:44:47 +00:00
return 0 ;
}
2017-01-09 09:54:49 +00:00
static int ignite_3 ( moo_t * moo )
2016-12-26 18:44:47 +00:00
{
/* Register kernel classes manually created so far to the system dictionary */
2017-01-09 09:54:49 +00:00
static moo_ooch_t str_processor [ ] = { ' P ' , ' r ' , ' o ' , ' c ' , ' e ' , ' s ' , ' s ' , ' o ' , ' r ' } ;
2017-02-10 07:38:29 +00:00
static moo_ooch_t str_dicnew [ ] = { ' n ' , ' e ' , ' w ' , ' : ' } ;
2018-06-20 18:01:04 +00:00
static moo_ooch_t str_dicputassoc [ ] = { ' _ ' , ' _ ' , ' p ' , ' u ' , ' t ' , ' _ ' , ' a ' , ' s ' , ' s ' , ' o ' , ' c ' , ' : ' } ;
2019-06-23 04:49:38 +00:00
static moo_ooch_t str_does_not_understand [ ] = { ' d ' , ' o ' , ' e ' , ' s ' , ' N ' , ' o ' , ' t ' , ' U ' , ' n ' , ' d ' , ' e ' , ' r ' , ' s ' , ' t ' , ' a ' , ' n ' , ' d ' , ' : ' } ;
static moo_ooch_t str_primitive_failed [ ] = { ' p ' , ' r ' , ' i ' , ' m ' , ' i ' , ' t ' , ' i ' , ' v ' , ' e ' , ' F ' , ' a ' , ' i ' , ' l ' , ' e ' , ' d ' } ;
static moo_ooch_t str_unwindto_return [ ] = { ' u ' , ' n ' , ' w ' , ' i ' , ' n ' , ' d ' , ' T ' , ' o ' , ' : ' , ' r ' , ' e ' , ' t ' , ' u ' , ' r ' , ' n ' , ' : ' } ;
2017-01-09 09:54:49 +00:00
moo_oow_t i ;
2017-05-20 02:27:48 +00:00
moo_oop_t sym ;
moo_oop_class_t cls ;
2016-12-26 18:44:47 +00:00
2017-01-09 09:54:49 +00:00
for ( i = 0 ; i < MOO_COUNTOF ( kernel_classes ) ; i + + )
2016-12-26 18:44:47 +00:00
{
2018-12-08 17:36:20 +00:00
sym = moo_makesymbol ( moo , kernel_classes [ i ] . name , kernel_classes [ i ] . len ) ;
2016-12-26 18:44:47 +00:00
if ( ! sym ) return - 1 ;
2017-05-20 02:27:48 +00:00
cls = * ( moo_oop_class_t * ) ( ( moo_uint8_t * ) moo + kernel_classes [ i ] . offset ) ;
2018-12-16 17:35:46 +00:00
MOO_STORE_OOP ( moo , ( moo_oop_t * ) & cls - > name , sym ) ;
2018-12-31 16:47:54 +00:00
MOO_STORE_OOP ( moo , ( moo_oop_t * ) & cls - > nsup , ( moo_oop_t ) moo - > sysdic ) ;
2016-12-26 18:44:47 +00:00
2017-05-20 02:27:48 +00:00
if ( ! moo_putatsysdic ( moo , sym , ( moo_oop_t ) cls ) ) return - 1 ;
2016-12-26 18:44:47 +00:00
}
2017-05-20 02:27:48 +00:00
/* Attach the system dictionary to the nsdic field of the System class */
2018-12-31 16:47:54 +00:00
MOO_STORE_OOP ( moo , ( moo_oop_t * ) & moo - > _system - > nsdic , ( moo_oop_t ) moo - > sysdic ) ;
2017-05-20 02:27:48 +00:00
/* Set the name field of the system dictionary */
2018-12-31 16:47:54 +00:00
MOO_STORE_OOP ( moo , ( moo_oop_t * ) & moo - > sysdic - > name , ( moo_oop_t ) moo - > _system - > name ) ;
2017-05-20 02:27:48 +00:00
/* Set the owning class field of the system dictionary, it's circular here */
2018-12-31 16:47:54 +00:00
MOO_STORE_OOP ( moo , ( moo_oop_t * ) & moo - > sysdic - > nsup , ( moo_oop_t ) moo - > _system ) ;
2017-05-20 02:27:48 +00:00
2016-12-26 18:44:47 +00:00
/* Make the process scheduler avaialble as the global name 'Processor' */
2018-12-08 17:36:20 +00:00
sym = moo_makesymbol ( moo , str_processor , MOO_COUNTOF ( str_processor ) ) ;
2016-12-26 18:44:47 +00:00
if ( ! sym ) return - 1 ;
2017-01-09 09:54:49 +00:00
if ( ! moo_putatsysdic ( moo , sym , ( moo_oop_t ) moo - > processor ) ) return - 1 ;
2016-12-26 18:44:47 +00:00
2018-12-08 17:36:20 +00:00
sym = moo_makesymbol ( moo , str_dicnew , MOO_COUNTOF ( str_dicnew ) ) ;
2017-02-10 07:38:29 +00:00
if ( ! sym ) return - 1 ;
2017-02-15 11:57:24 +00:00
moo - > dicnewsym = ( moo_oop_char_t ) sym ;
2017-02-10 07:38:29 +00:00
2018-12-08 17:36:20 +00:00
sym = moo_makesymbol ( moo , str_dicputassoc , MOO_COUNTOF ( str_dicputassoc ) ) ;
2017-02-10 07:38:29 +00:00
if ( ! sym ) return - 1 ;
2017-02-15 11:57:24 +00:00
moo - > dicputassocsym = ( moo_oop_char_t ) sym ;
2017-02-10 07:38:29 +00:00
2019-06-23 04:49:38 +00:00
sym = moo_makesymbol ( moo , str_does_not_understand , MOO_COUNTOF ( str_does_not_understand ) ) ;
if ( ! sym ) return - 1 ;
moo - > does_not_understand_sym = ( moo_oop_char_t ) sym ;
sym = moo_makesymbol ( moo , str_primitive_failed , MOO_COUNTOF ( str_primitive_failed ) ) ;
if ( ! sym ) return - 1 ;
moo - > primitive_failed_sym = ( moo_oop_char_t ) sym ;
sym = moo_makesymbol ( moo , str_unwindto_return , MOO_COUNTOF ( str_unwindto_return ) ) ;
if ( ! sym ) return - 1 ;
moo - > unwindto_return_sym = ( moo_oop_char_t ) sym ;
2016-12-26 18:44:47 +00:00
return 0 ;
}
2018-11-30 10:33:17 +00:00
int moo_ignite ( moo_t * moo , moo_oow_t heapsz )
2016-12-26 18:44:47 +00:00
{
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , moo - > _nil = = MOO_NULL ) ;
2016-12-26 18:44:47 +00:00
2018-11-30 13:37:15 +00:00
if ( moo - > heap ) moo_killheap ( moo , moo - > heap ) ;
moo - > heap = moo_makeheap ( moo , heapsz ) ;
2020-10-26 16:43:09 +00:00
if ( MOO_UNLIKELY ( ! moo - > heap ) ) return - 1 ;
2018-11-30 10:33:17 +00:00
2018-12-09 07:21:16 +00:00
moo - > igniting = 1 ;
2018-12-08 15:36:20 +00:00
moo - > _nil = moo_allocbytes ( moo , MOO_SIZEOF ( moo_obj_t ) ) ;
2020-10-26 16:43:09 +00:00
if ( MOO_UNLIKELY ( ! moo - > _nil ) ) goto oops ;
2016-12-26 18:44:47 +00:00
2019-09-22 16:26:30 +00:00
moo - > _nil - > _flags = MOO_OBJ_MAKE_FLAGS ( MOO_OBJ_TYPE_OOP , MOO_SIZEOF ( moo_oop_t ) , 0 , 1 , moo - > igniting , 0 , 0 , 0 , 0 , 0 ) ;
2017-01-09 09:54:49 +00:00
moo - > _nil - > _size = 0 ;
2016-12-26 18:44:47 +00:00
2018-12-09 07:21:16 +00:00
if ( ignite_1 ( moo ) < = - 1 | | ignite_2 ( moo ) < = - 1 | | ignite_3 ( moo ) ) goto oops ; ;
2016-12-26 18:44:47 +00:00
2018-12-09 07:21:16 +00:00
moo - > igniting = 0 ;
2016-12-26 18:44:47 +00:00
return 0 ;
2018-12-09 07:21:16 +00:00
oops :
moo - > igniting = 0 ;
return - 1 ;
2016-12-26 18:44:47 +00:00
}
/* -----------------------------------------------------------------------
* GARBAGE COLLECTOR
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-01-09 09:54:49 +00:00
static void compact_symbol_table ( moo_t * moo , moo_oop_t _nil )
2015-04-30 15:56:05 +00:00
{
2018-12-08 15:35:26 +00:00
moo_oop_oop_t bucket ;
2018-12-25 16:00:47 +00:00
moo_oop_t tmp ;
2017-01-09 09:54:49 +00:00
moo_oow_t i , x , y , z ;
moo_oow_t bucket_size , index ;
moo_ooi_t tally ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
# if defined(MOO_SUPPORT_GC_DURING_IGNITION)
if ( ! moo - > symtab ) return ; /* symbol table has not been created */
2015-05-07 15:58:04 +00:00
# endif
2017-01-09 09:54:49 +00:00
/* the symbol table doesn't allow more data items than MOO_SMOOI_MAX.
* so moo - > symtab - > tally must always be a small integer */
MOO_ASSERT ( moo , MOO_OOP_IS_SMOOI ( moo - > symtab - > tally ) ) ;
tally = MOO_OOP_TO_SMOOI ( moo - > symtab - > tally ) ;
MOO_ASSERT ( moo , tally > = 0 ) ; /* it must not be less than 0 */
2015-04-30 15:56:05 +00:00
if ( tally < = 0 ) return ;
2018-12-08 15:35:26 +00:00
bucket = moo - > symtab - > bucket ;
2019-08-07 05:33:35 +00:00
/* [NOTE] in theory, the bucket size can be greater than MOO_SMOOI_MAX
2015-11-20 09:05:55 +00:00
* as it is an internal header field and is of an unsigned type */
2018-12-08 15:35:26 +00:00
bucket_size = MOO_OBJ_GET_SIZE ( bucket ) ;
2015-11-20 09:05:55 +00:00
2015-05-07 15:58:04 +00:00
for ( index = 0 ; index < bucket_size ; )
2015-04-30 15:56:05 +00:00
{
2018-12-25 16:00:47 +00:00
tmp = MOO_OBJ_GET_OOP_VAL ( bucket , index ) ;
if ( MOO_OBJ_GET_FLAGS_PERM ( tmp ) | | MOO_OBJ_GET_FLAGS_MOVED ( tmp ) )
2015-04-30 15:56:05 +00:00
{
index + + ;
continue ;
}
2018-12-25 16:00:47 +00:00
MOO_ASSERT ( moo , tmp ! = _nil ) ;
2018-12-26 08:29:20 +00:00
MOO_LOG2 ( moo , MOO_LOG_GC | MOO_LOG_INFO , " Compacting away a symbol - %.*js \n " , MOO_OBJ_GET_SIZE ( tmp ) , MOO_OBJ_GET_CHAR_SLOT ( tmp ) ) ;
2015-04-30 15:56:05 +00:00
2020-10-18 16:53:43 +00:00
/* delete a symbol table entry which has not been moved (excluding permanent entries) */
2015-05-07 15:58:04 +00:00
for ( i = 0 , x = index , y = index ; i < bucket_size ; i + + )
2015-04-30 15:56:05 +00:00
{
2015-05-07 15:58:04 +00:00
y = ( y + 1 ) % bucket_size ;
2015-04-30 15:56:05 +00:00
/* done if the slot at the current hash index is _nil */
2018-12-25 16:00:47 +00:00
tmp = MOO_OBJ_GET_OOP_VAL ( bucket , y ) ;
if ( tmp = = _nil ) break ;
2015-04-30 15:56:05 +00:00
/* get the natural hash index for the data in the slot
* at the current hash index */
2018-12-25 16:00:47 +00:00
MOO_ASSERT ( moo , MOO_CLASSOF ( moo , tmp ) = = moo - > _symbol ) ;
2019-03-06 01:58:51 +00:00
z = moo_hash_oochars ( MOO_OBJ_GET_CHAR_SLOT ( tmp ) , MOO_OBJ_GET_SIZE ( tmp ) ) % bucket_size ;
2015-04-30 15:56:05 +00:00
/* move an element if necessary */
2018-12-26 08:29:20 +00:00
if ( ( y > x & & ( z < = x | | z > y ) ) | | ( y < x & & ( z < = x & & z > y ) ) )
2015-04-30 15:56:05 +00:00
{
2018-12-25 16:00:47 +00:00
tmp = MOO_OBJ_GET_OOP_VAL ( bucket , y ) ;
/* this function is called as part of garbage collection.
* i must not use MOO_STORE_OOP for object relocation */
MOO_OBJ_SET_OOP_VAL ( bucket , x , tmp ) ;
2015-04-30 15:56:05 +00:00
x = y ;
}
}
2018-12-25 16:00:47 +00:00
MOO_OBJ_SET_OOP_VAL ( bucket , x , _nil ) ;
2015-04-30 15:56:05 +00:00
tally - - ;
}
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , tally > = 0 ) ;
MOO_ASSERT ( moo , tally < = MOO_SMOOI_MAX ) ;
moo - > symtab - > tally = MOO_SMOOI_TO_OOP ( tally ) ;
2015-04-30 15:56:05 +00:00
}
2019-09-17 23:15:20 +00:00
moo_oow_t moo_getobjpayloadbytes ( moo_t * moo , moo_oop_t oop )
2015-10-30 15:36:37 +00:00
{
2019-09-16 14:16:55 +00:00
moo_oow_t nbytes ;
2015-10-30 15:36:37 +00:00
2019-09-17 23:15:20 +00:00
MOO_ASSERT ( moo , MOO_OOP_IS_POINTER ( oop ) ) ;
2017-01-09 09:54:49 +00:00
if ( MOO_OBJ_GET_FLAGS_TRAILER ( oop ) )
2015-10-30 15:36:37 +00:00
{
/* only an OOP object can have the trailer.
*
* | _flags |
* | _size | < - - if it ' s 3
* | _class |
* | X |
* | X |
* | X |
* | Y | < - - it may exist if EXTRA is set in _flags .
2019-09-19 14:10:00 +00:00
* | Z | < - - if TRAILER is set , it is a word indicating the number of bytes in the trailer
* | | | | | < - - trailer bytes . it ' s aligned to a word boundary .
* | hash | < - - if HASH is set to 2 in _flags , a word is used to store a hash value
2015-10-30 15:36:37 +00:00
*/
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , MOO_OBJ_GET_FLAGS_TYPE ( oop ) = = MOO_OBJ_TYPE_OOP ) ;
MOO_ASSERT ( moo , MOO_OBJ_GET_FLAGS_UNIT ( oop ) = = MOO_SIZEOF ( moo_oow_t ) ) ;
MOO_ASSERT ( moo , MOO_OBJ_GET_FLAGS_EXTRA ( oop ) = = 0 ) ; /* no 'extra' for an OOP object */
2015-10-30 15:36:37 +00:00
2018-12-25 16:00:47 +00:00
nbytes = MOO_OBJ_BYTESOF ( oop ) + MOO_SIZEOF ( moo_oow_t ) + MOO_OBJ_GET_TRAILER_SIZE ( oop ) ;
2015-10-30 15:36:37 +00:00
}
else
{
/* calculate the payload size in bytes */
2019-09-16 14:16:55 +00:00
nbytes = MOO_OBJ_BYTESOF ( oop ) ;
2015-10-30 15:36:37 +00:00
}
2019-09-17 23:15:20 +00:00
nbytes = MOO_ALIGN ( nbytes , MOO_SIZEOF ( moo_oop_t ) ) ;
2019-09-19 14:10:00 +00:00
if ( MOO_OBJ_GET_FLAGS_HASH ( oop ) = = MOO_OBJ_FLAGS_HASH_STORED )
2019-09-17 23:15:20 +00:00
{
MOO_STATIC_ASSERT ( MOO_SIZEOF ( moo_oop_t ) = = MOO_SIZEOF ( moo_oow_t ) ) ;
nbytes + = MOO_SIZEOF ( moo_oow_t ) ;
}
2019-09-16 14:16:55 +00:00
2019-09-17 23:15:20 +00:00
return nbytes ;
2015-10-30 15:36:37 +00:00
}
2020-10-18 16:53:43 +00:00
static moo_rbt_walk_t call_module_gc ( moo_rbt_t * rbt , moo_rbt_pair_t * pair , void * ctx )
{
moo_t * moo = ( moo_t * ) ctx ;
moo_mod_data_t * mdp ;
mdp = MOO_RBT_VPTR ( pair ) ;
MOO_ASSERT ( moo , mdp ! = MOO_NULL ) ;
if ( mdp - > mod . gc ) mdp - > mod . gc ( moo , & mdp - > mod ) ;
return MOO_RBT_WALK_FORWARD ;
}
/* ----------------------------------------------------------------------- */
# if defined(MOO_ENABLE_GC_MARK_SWEEP)
2020-10-26 16:43:09 +00:00
#if 0
2020-11-27 05:13:02 +00:00
static MOO_INLINE void gc_ms_mark ( moo_t * moo , moo_oop_t oop )
2020-10-18 16:53:43 +00:00
{
moo_oow_t i , sz ;
# if defined(MOO_SUPPORT_GC_DURING_IGNITION)
if ( ! oop ) return ;
# endif
if ( ! MOO_OOP_IS_POINTER ( oop ) ) return ;
if ( MOO_OBJ_GET_FLAGS_MOVED ( oop ) ) return ; /* already marked */
MOO_OBJ_SET_FLAGS_MOVED ( oop , 1 ) ; /* mark */
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) MOO_OBJ_GET_CLASS ( oop ) ) ; /* TODO: remove recursion */
2020-10-18 16:53:43 +00:00
if ( MOO_OBJ_GET_FLAGS_TYPE ( oop ) = = MOO_OBJ_TYPE_OOP )
{
moo_oow_t size , i ;
/* is it really better to use a flag bit in the header to
* determine that it is an instance of process ? */
if ( MOO_UNLIKELY ( MOO_OBJ_GET_FLAGS_PROC ( oop ) ) )
{
/* the stack in a process object doesn't need to be
* scanned in full . the slots above the stack pointer
* are garbages . */
size = MOO_PROCESS_NAMED_INSTVARS + MOO_OOP_TO_SMOOI ( ( ( moo_oop_process_t ) oop ) - > sp ) + 1 ;
MOO_ASSERT ( moo , size < = MOO_OBJ_GET_SIZE ( oop ) ) ;
}
else
{
size = MOO_OBJ_GET_SIZE ( oop ) ;
}
for ( i = 0 ; i < size ; i + + )
{
moo_oop_t tmp = MOO_OBJ_GET_OOP_VAL ( oop , i ) ;
2020-11-27 05:13:02 +00:00
if ( MOO_OOP_IS_POINTER ( tmp ) ) gc_ms_mark ( moo , tmp ) ; /* TODO: no resursion */
2020-10-18 16:53:43 +00:00
}
}
}
2020-10-26 16:43:09 +00:00
# else
2020-11-27 05:13:02 +00:00
static MOO_INLINE void gc_ms_mark_object ( moo_t * moo , moo_oop_t oop )
2020-10-26 16:43:09 +00:00
{
# if defined(MOO_SUPPORT_GC_DURING_IGNITION)
if ( ! oop ) return ;
# endif
if ( ! MOO_OOP_IS_POINTER ( oop ) | | MOO_OBJ_GET_FLAGS_MOVED ( oop ) ) return ; /* non-pointer or already marked */
MOO_OBJ_SET_FLAGS_MOVED ( oop , 1 ) ; /* mark */
MOO_ASSERT ( moo , moo - > gci . stack . len < moo - > gci . stack . capa ) ;
moo - > gci . stack . ptr [ moo - > gci . stack . len + + ] = oop ; /* push */
if ( moo - > gci . stack . len > moo - > gci . stack . max ) moo - > gci . stack . max = moo - > gci . stack . len ;
}
2020-11-27 05:13:02 +00:00
static MOO_INLINE void gc_ms_scan_stack ( moo_t * moo )
2020-10-26 16:43:09 +00:00
{
moo_oop_t oop ;
while ( moo - > gci . stack . len > 0 )
{
oop = moo - > gci . stack . ptr [ - - moo - > gci . stack . len ] ;
2020-11-27 05:13:02 +00:00
gc_ms_mark_object ( moo , ( moo_oop_t ) MOO_OBJ_GET_CLASS ( oop ) ) ;
2020-10-26 16:43:09 +00:00
if ( MOO_OBJ_GET_FLAGS_TYPE ( oop ) = = MOO_OBJ_TYPE_OOP )
{
moo_oow_t size , i ;
/* is it really better to use a flag bit in the header to
* determine that it is an instance of process ? */
if ( MOO_UNLIKELY ( MOO_OBJ_GET_FLAGS_PROC ( oop ) ) )
{
/* the stack in a process object doesn't need to be
* scanned in full . the slots above the stack pointer
* are garbages . */
size = MOO_PROCESS_NAMED_INSTVARS + MOO_OOP_TO_SMOOI ( ( ( moo_oop_process_t ) oop ) - > sp ) + 1 ;
MOO_ASSERT ( moo , size < = MOO_OBJ_GET_SIZE ( oop ) ) ;
}
else
{
size = MOO_OBJ_GET_SIZE ( oop ) ;
}
for ( i = 0 ; i < size ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark_object ( moo , MOO_OBJ_GET_OOP_VAL ( oop , i ) ) ;
2020-10-26 16:43:09 +00:00
}
}
}
}
2020-11-27 05:13:02 +00:00
static MOO_INLINE void gc_ms_mark ( moo_t * moo , moo_oop_t oop )
2020-10-26 16:43:09 +00:00
{
2020-11-27 05:13:02 +00:00
gc_ms_mark_object ( moo , oop ) ;
gc_ms_scan_stack ( moo ) ;
2020-10-26 16:43:09 +00:00
}
# endif
2020-10-18 16:53:43 +00:00
2020-11-27 05:13:02 +00:00
static MOO_INLINE void gc_ms_mark_roots ( moo_t * moo )
2020-10-18 16:53:43 +00:00
{
moo_oow_t i , gcfin_count ;
moo_evtcb_t * cb ;
2020-10-23 14:25:10 +00:00
if ( moo - > processor & & moo - > processor - > active )
2020-10-22 10:46:45 +00:00
{
MOO_ASSERT ( moo , ( moo_oop_t ) moo - > processor ! = moo - > _nil ) ;
MOO_ASSERT ( moo , ( moo_oop_t ) moo - > processor - > active ! = moo - > _nil ) ;
2020-10-23 14:25:10 +00:00
2020-10-22 10:46:45 +00:00
/* commit the stack pointer to the active process because
2020-10-23 14:25:10 +00:00
* gc needs the correct stack pointer for a process object */
2020-10-22 10:46:45 +00:00
moo - > processor - > active - > sp = MOO_SMOOI_TO_OOP ( moo - > sp ) ;
2020-10-23 14:25:10 +00:00
}
2020-10-23 09:21:55 +00:00
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , moo - > _nil ) ;
gc_ms_mark ( moo , moo - > _true ) ;
gc_ms_mark ( moo , moo - > _false ) ;
2020-10-18 16:53:43 +00:00
for ( i = 0 ; i < MOO_COUNTOF ( kernel_classes ) ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , * ( moo_oop_t * ) ( ( moo_uint8_t * ) moo + kernel_classes [ i ] . offset ) ) ;
2020-10-18 16:53:43 +00:00
}
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sysdic ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > processor ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > nil_process ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > dicnewsym ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > dicputassocsym ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > does_not_understand_sym ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > primitive_failed_sym ) ;
gc_ms_mark ( moo , ( moo_oop_t ) moo - > unwindto_return_sym ) ;
2020-10-18 16:53:43 +00:00
for ( i = 0 ; i < moo - > sem_list_count ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sem_list [ i ] ) ;
2020-10-18 16:53:43 +00:00
}
for ( i = 0 ; i < moo - > sem_heap_count ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sem_heap [ i ] ) ;
2020-10-18 16:53:43 +00:00
}
for ( i = 0 ; i < moo - > sem_io_tuple_count ; i + + )
{
if ( moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_INPUT ] )
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_INPUT ] ) ;
2020-10-18 16:53:43 +00:00
if ( moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_OUTPUT ] )
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_OUTPUT ] ) ;
2020-10-18 16:53:43 +00:00
}
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > sem_gcfin ) ;
2020-10-18 16:53:43 +00:00
for ( i = 0 ; i < moo - > proc_map_capa ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , moo - > proc_map [ i ] ) ;
2020-10-18 16:53:43 +00:00
}
for ( i = 0 ; i < moo - > volat_count ; i + + )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , * moo - > volat_stack [ i ] ) ;
2020-10-18 16:53:43 +00:00
}
2020-11-27 05:13:02 +00:00
if ( moo - > initial_context ) gc_ms_mark ( moo , ( moo_oop_t ) moo - > initial_context ) ;
if ( moo - > active_context ) gc_ms_mark ( moo , ( moo_oop_t ) moo - > active_context ) ;
if ( moo - > active_method ) gc_ms_mark ( moo , ( moo_oop_t ) moo - > active_method ) ;
2020-10-18 16:53:43 +00:00
moo_rbt_walk ( & moo - > modtab , call_module_gc , moo ) ;
for ( cb = moo - > evtcb_list ; cb ; cb = cb - > next )
{
if ( cb - > gc ) cb - > gc ( moo ) ;
}
2020-10-19 10:10:40 +00:00
gcfin_count = move_finalizable_objects ( moo ) ; /* mark finalizable objects */
2020-10-18 16:53:43 +00:00
if ( moo - > symtab )
{
compact_symbol_table ( moo , moo - > _nil ) ; /* delete symbol table entries that are not marked */
#if 0
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , ( moo_oop_t ) moo - > symtab ) ; /* mark the symbol table */
2020-10-18 16:53:43 +00:00
# else
MOO_OBJ_SET_FLAGS_MOVED ( moo - > symtab , 1 ) ; /* mark */
MOO_OBJ_SET_FLAGS_MOVED ( moo - > symtab - > bucket , 1 ) ; /* mark */
# endif
}
if ( gcfin_count > 0 ) moo - > sem_gcfin_sigreq = 1 ;
if ( moo - > active_method ) moo - > active_code = MOO_METHOD_GET_CODE_BYTE ( moo - > active_method ) ; /* update moo->active_code */
/* invalidate method cache. TODO: GCing entries on the method cache is also one way instead of full invalidation */
moo_clearmethodcache ( moo ) ;
}
2020-11-27 05:13:02 +00:00
void moo_gc_ms_sweep_lazy ( moo_t * moo , moo_oow_t allocsize )
{
moo_gchdr_t * curr , * next , * prev ;
moo_oop_t obj ;
moo_oow_t freed_size ;
if ( ! moo - > gci . ls . curr ) return ;
freed_size = 0 ;
//printf ("starting lazy sweep...gci.ls.curr [%p]\n", moo->gci.ls.curr);
prev = moo - > gci . ls . prev ;
curr = moo - > gci . ls . curr ;
while ( curr )
{
next = curr - > next ;
obj = ( moo_oop_t ) ( curr + 1 ) ;
if ( MOO_OBJ_GET_FLAGS_MOVED ( obj ) ) /* if marked */
{
MOO_OBJ_SET_FLAGS_MOVED ( obj , 0 ) ; /* unmark */
prev = curr ;
}
else
{
moo_oow_t objsize ;
if ( prev ) prev - > next = next ;
else moo - > gci . b = next ;
objsize = MOO_SIZEOF ( moo_obj_t ) + moo_getobjpayloadbytes ( moo , obj ) ;
freed_size + = objsize ;
moo - > gci . bsz - = objsize ;
moo_freeheapmem ( moo , moo - > heap , curr ) ; /* destroy */
if ( freed_size > allocsize ) /* TODO: can it secure large enough space? */
{
//printf ("stopping lazy sweeping after %lu free, allocsize %lu\n", (unsigned long int)freed_size, (unsigned long int)allocsize);
moo - > gci . ls . curr = next ; /* let the next lazy sweeping begin at this point */
moo - > gci . ls . prev = prev ;
//printf ("finished lazy sweep...\n");
return ;
}
}
curr = next ;
}
moo - > gci . ls . curr = MOO_NULL ;
//printf ("finished lazy sweep...\n");
}
static MOO_INLINE void gc_ms_sweep ( moo_t * moo )
2020-10-18 16:53:43 +00:00
{
moo_gchdr_t * curr , * next , * prev ;
moo_oop_t obj ;
prev = MOO_NULL ;
2020-10-26 16:43:09 +00:00
curr = moo - > gci . b ;
2020-10-18 16:53:43 +00:00
while ( curr )
{
next = curr - > next ;
obj = ( moo_oop_t ) ( curr + 1 ) ;
2020-11-27 05:13:02 +00:00
if ( MOO_OBJ_GET_FLAGS_MOVED ( obj ) ) /* if marked */
2020-10-18 16:53:43 +00:00
{
2020-11-27 05:13:02 +00:00
MOO_OBJ_SET_FLAGS_MOVED ( obj , 0 ) ; /* unmark */
2020-10-18 16:53:43 +00:00
prev = curr ;
}
else
{
if ( prev ) prev - > next = next ;
2020-10-26 16:43:09 +00:00
else moo - > gci . b = next ;
moo - > gci . bsz - = MOO_SIZEOF ( moo_obj_t ) + moo_getobjpayloadbytes ( moo , obj ) ;
2020-11-27 05:13:02 +00:00
moo_freeheapmem ( moo , moo - > heap , curr ) ; /* destroy */
2020-10-18 16:53:43 +00:00
}
curr = next ;
}
2020-11-27 05:13:02 +00:00
printf ( " finised full sweep... \n " ) ;
moo - > gci . ls . curr = MOO_NULL ;
2020-10-18 16:53:43 +00:00
}
# endif
/* ----------------------------------------------------------------------- */
2020-11-27 05:13:02 +00:00
static moo_oop_t gc_ss_move_oop ( moo_t * moo , moo_oop_t oop )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
# if defined(MOO_SUPPORT_GC_DURING_IGNITION)
2015-05-07 15:58:04 +00:00
if ( ! oop ) return oop ;
# endif
2017-01-09 09:54:49 +00:00
if ( ! MOO_OOP_IS_POINTER ( oop ) ) return oop ;
2015-04-30 15:56:05 +00:00
2018-12-08 17:36:20 +00:00
if ( MOO_OBJ_GET_FLAGS_PERM ( oop ) ) return oop ;
2017-01-09 09:54:49 +00:00
if ( MOO_OBJ_GET_FLAGS_MOVED ( oop ) )
2015-04-30 15:56:05 +00:00
{
/* 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 . */
2017-02-15 11:57:24 +00:00
return ( moo_oop_t ) MOO_OBJ_GET_CLASS ( oop ) ;
2015-04-30 15:56:05 +00:00
}
else
{
2019-09-17 23:15:20 +00:00
moo_oow_t nbytes_aligned , extra_bytes = 0 ;
2017-01-09 09:54:49 +00:00
moo_oop_t tmp ;
2015-04-30 15:56:05 +00:00
2019-09-17 23:15:20 +00:00
nbytes_aligned = moo_getobjpayloadbytes ( moo , oop ) ;
2019-09-19 14:10:00 +00:00
if ( MOO_OBJ_GET_FLAGS_HASH ( oop ) = = MOO_OBJ_FLAGS_HASH_CALLED )
2019-09-17 23:15:20 +00:00
{
2019-09-19 14:10:00 +00:00
MOO_STATIC_ASSERT ( MOO_SIZEOF ( moo_oop_t ) = = MOO_SIZEOF ( moo_oow_t ) ) ;
/* don't need explicit alignment since oop and oow have the same size
extra_bytes = MOO_ALIGN ( MOO_SIZEOF ( moo_oow_t ) , MOO_SIZEOF ( moo_oop_t ) ) ; */
extra_bytes = MOO_SIZEOF ( moo_oow_t ) ;
2019-09-17 23:15:20 +00:00
}
2015-04-30 15:56:05 +00:00
/* allocate space in the new heap */
2019-09-17 23:15:20 +00:00
tmp = moo_allocheapspace ( moo , & moo - > heap - > newspace , MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned + extra_bytes ) ;
2015-04-30 15:56:05 +00:00
/* 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 . */
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , tmp ! = MOO_NULL ) ;
2015-04-30 15:56:05 +00:00
/* copy the payload to the new object */
2017-01-09 09:54:49 +00:00
MOO_MEMCPY ( tmp , oop , MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ) ;
2015-04-30 15:56:05 +00:00
/* mark the old object that it has migrated to the new heap */
2018-12-08 17:36:20 +00:00
MOO_OBJ_SET_FLAGS_MOVED ( oop , 1 ) ;
2015-04-30 15:56:05 +00:00
/* 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 . */
2017-01-09 09:54:49 +00:00
MOO_OBJ_SET_CLASS ( oop , tmp ) ;
2015-05-07 15:58:04 +00:00
2019-09-17 23:15:20 +00:00
if ( extra_bytes )
{
2019-09-19 14:10:00 +00:00
MOO_OBJ_SET_FLAGS_HASH ( tmp , MOO_OBJ_FLAGS_HASH_STORED ) ;
* ( moo_oow_t * ) ( ( moo_uint8_t * ) tmp + MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ) = ( moo_oow_t ) oop % ( MOO_SMOOI_MAX + 1 ) ;
2019-09-17 23:15:20 +00:00
}
2015-04-30 15:56:05 +00:00
/* return the new object */
return tmp ;
}
}
2020-11-27 05:13:02 +00:00
static moo_uint8_t * gc_ss_scan_space ( moo_t * moo , moo_uint8_t * ptr , moo_uint8_t * * end )
2015-04-30 15:56:05 +00:00
{
2018-12-10 09:30:37 +00:00
while ( ptr < * end ) /* the end pointer may get changed, especially the new space. so it's moo_int8_t** */
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oow_t i ;
moo_oow_t nbytes_aligned ;
2018-12-26 08:29:20 +00:00
moo_oop_t oop , tmp ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
oop = ( moo_oop_t ) ptr ;
2018-12-26 10:32:31 +00:00
MOO_ASSERT ( moo , MOO_OOP_IS_POINTER ( oop ) ) ;
2019-09-17 23:15:20 +00:00
nbytes_aligned = moo_getobjpayloadbytes ( moo , oop ) ;
2019-09-16 14:16:55 +00:00
2020-11-27 05:13:02 +00:00
tmp = moo_updateoopforgc ( moo , ( moo_oop_t ) MOO_OBJ_GET_CLASS ( oop ) ) ;
2018-12-26 08:29:20 +00:00
MOO_OBJ_SET_CLASS ( oop , tmp ) ;
2018-12-26 10:32:31 +00:00
2017-01-09 09:54:49 +00:00
if ( MOO_OBJ_GET_FLAGS_TYPE ( oop ) = = MOO_OBJ_TYPE_OOP )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oow_t size ;
2015-06-11 09:11:18 +00:00
2019-09-15 15:41:24 +00:00
/* is it really better to use a flag bit in the header to
* determine that it is an instance of process ? */
2018-12-29 15:16:58 +00:00
if ( MOO_UNLIKELY ( MOO_OBJ_GET_FLAGS_PROC ( oop ) ) )
2016-02-15 18:13:26 +00:00
{
/* the stack in a process object doesn't need to be
* scanned in full . the slots above the stack pointer
* are garbages . */
2018-12-09 17:14:56 +00:00
size = MOO_PROCESS_NAMED_INSTVARS + MOO_OOP_TO_SMOOI ( ( ( moo_oop_process_t ) oop ) - > sp ) + 1 ;
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , size < = MOO_OBJ_GET_SIZE ( oop ) ) ;
2016-02-15 18:13:26 +00:00
}
2015-06-11 09:11:18 +00:00
else
{
2017-01-09 09:54:49 +00:00
size = MOO_OBJ_GET_SIZE ( oop ) ;
2015-06-11 09:11:18 +00:00
}
2015-04-30 15:56:05 +00:00
2015-06-11 09:11:18 +00:00
for ( i = 0 ; i < size ; i + + )
2015-04-30 15:56:05 +00:00
{
2018-12-25 16:00:47 +00:00
tmp = MOO_OBJ_GET_OOP_VAL ( oop , i ) ;
if ( MOO_OOP_IS_POINTER ( tmp ) )
2018-12-09 17:14:56 +00:00
{
2018-12-25 16:00:47 +00:00
/* i must not use MOO_STORE_OOP() as this operation is
* part of garbage collection . */
2020-11-27 05:13:02 +00:00
tmp = moo_updateoopforgc ( moo , tmp ) ;
2018-12-25 16:00:47 +00:00
MOO_OBJ_SET_OOP_VAL ( oop , i , tmp ) ;
2018-12-09 17:14:56 +00:00
}
2015-04-30 15:56:05 +00:00
}
}
2015-05-07 15:58:04 +00:00
2017-06-16 09:45:22 +00:00
if ( MOO_OBJ_GET_FLAGS_TRAILER ( oop ) )
{
moo_oop_class_t c ;
moo_trgc_t trgc ;
/* i use SMPTR(0) to indicate no trailer gc callback.
* i don ' t use moo - > _nil because c - > trgc field may not have
* been updated to a new nil address while moo - > _nil could
* have been updated in the process of garbage collection .
* this comment will be invalidated when moo - > _nil is
* stored in a permanent heap or GC gets changed to
* a non - copying collector . no matter what GC implementation
* i choose , using SMPTR ( 0 ) for this purpose is safe . */
c = MOO_OBJ_GET_CLASS ( oop ) ;
MOO_ASSERT ( moo , MOO_OOP_IS_SMPTR ( c - > trgc ) ) ;
trgc = MOO_OOP_TO_SMPTR ( c - > trgc ) ;
if ( trgc ) trgc ( moo , oop ) ;
}
2018-12-10 09:30:37 +00:00
ptr + = MOO_SIZEOF ( moo_obj_t ) + nbytes_aligned ;
2015-04-30 15:56:05 +00:00
}
/* return the pointer to the beginning of the free space in the heap */
return ptr ;
}
2017-03-19 14:18:37 +00:00
2020-11-27 05:13:02 +00:00
static void gc_ss_scan_roots ( moo_t * moo )
2015-04-30 15:56:05 +00:00
{
/*
* 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 .
*/
2018-12-09 17:14:56 +00:00
moo_uint8_t * newspace_scan_ptr ;
2018-11-30 13:37:15 +00:00
moo_space_t tmp ;
2017-01-09 09:54:49 +00:00
moo_oop_t old_nil ;
moo_oow_t i ;
2018-11-13 06:54:30 +00:00
moo_evtcb_t * cb ;
2017-07-27 08:32:16 +00:00
moo_oow_t gcfin_count ;
2015-04-30 15:56:05 +00:00
2017-01-09 09:54:49 +00:00
if ( moo - > active_context )
2015-06-11 09:11:18 +00:00
{
/* TODO: verify if this is correct */
2017-01-09 09:54:49 +00:00
MOO_ASSERT ( moo , ( moo_oop_t ) moo - > processor ! = moo - > _nil ) ;
MOO_ASSERT ( moo , ( moo_oop_t ) moo - > processor - > active ! = moo - > _nil ) ;
2020-10-23 09:21:55 +00:00
/* commit the stack pointer to the active process
* to limit scanning of the process stack properly */
2017-01-09 09:54:49 +00:00
moo - > processor - > active - > sp = MOO_SMOOI_TO_OOP ( moo - > sp ) ;
2015-06-11 09:11:18 +00:00
}
2017-01-09 09:54:49 +00:00
MOO_LOG4 ( moo , MOO_LOG_GC | MOO_LOG_INFO ,
2016-06-05 18:01:35 +00:00
" Starting GC curheap base %p ptr %p newheap base %p ptr %p \n " ,
2018-11-30 13:37:15 +00:00
moo - > heap - > curspace . base , moo - > heap - > curspace . ptr , moo - > heap - > newspace . base , moo - > heap - > newspace . ptr ) ;
2016-06-05 18:01:35 +00:00
2018-12-09 17:14:56 +00:00
newspace_scan_ptr = ( moo_uint8_t * ) MOO_ALIGN ( ( moo_uintptr_t ) moo - > heap - > newspace . base , MOO_SIZEOF ( moo_oop_t ) ) ;
2017-07-21 16:54:43 +00:00
2015-04-30 15:56:05 +00:00
/* TODO: allocate common objects like _nil and the root dictionary
* in the permanant heap . minimize moving around */
2017-01-09 09:54:49 +00:00
old_nil = moo - > _nil ;
2015-04-30 15:56:05 +00:00
/* move _nil and the root object table */
2020-11-27 05:13:02 +00:00
moo - > _nil = moo_updateoopforgc ( moo , moo - > _nil ) ;
moo - > _true = moo_updateoopforgc ( moo , moo - > _true ) ;
moo - > _false = moo_updateoopforgc ( moo , moo - > _false ) ;
2015-05-07 15:58:04 +00:00
2017-01-09 09:54:49 +00:00
for ( i = 0 ; i < MOO_COUNTOF ( kernel_classes ) ; i + + )
2016-12-26 18:44:47 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_t tmp ;
tmp = * ( moo_oop_t * ) ( ( moo_uint8_t * ) moo + kernel_classes [ i ] . offset ) ;
2020-11-27 05:13:02 +00:00
tmp = moo_updateoopforgc ( moo , tmp ) ;
2017-01-09 09:54:49 +00:00
* ( moo_oop_t * ) ( ( moo_uint8_t * ) moo + kernel_classes [ i ] . offset ) = tmp ;
2016-12-26 18:44:47 +00:00
}
2015-05-07 15:58:04 +00:00
2020-11-27 05:13:02 +00:00
moo - > sysdic = ( moo_oop_nsdic_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sysdic ) ;
moo - > processor = ( moo_oop_process_scheduler_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > processor ) ;
moo - > nil_process = ( moo_oop_process_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > nil_process ) ;
moo - > dicnewsym = ( moo_oop_char_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > dicnewsym ) ;
moo - > dicputassocsym = ( moo_oop_char_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > dicputassocsym ) ;
moo - > does_not_understand_sym = ( moo_oop_char_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > does_not_understand_sym ) ;
moo - > primitive_failed_sym = ( moo_oop_char_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > primitive_failed_sym ) ;
moo - > unwindto_return_sym = ( moo_oop_char_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > unwindto_return_sym ) ;
2015-05-07 15:58:04 +00:00
2017-01-09 09:54:49 +00:00
for ( i = 0 ; i < moo - > sem_list_count ; i + + )
2016-02-29 15:27:10 +00:00
{
2020-11-27 05:13:02 +00:00
moo - > sem_list [ i ] = ( moo_oop_semaphore_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sem_list [ i ] ) ;
2016-03-22 14:18:07 +00:00
}
2017-01-09 09:54:49 +00:00
for ( i = 0 ; i < moo - > sem_heap_count ; i + + )
2016-03-22 14:18:07 +00:00
{
2020-11-27 05:13:02 +00:00
moo - > sem_heap [ i ] = ( moo_oop_semaphore_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sem_heap [ i ] ) ;
2016-02-29 15:27:10 +00:00
}
2017-12-25 18:35:23 +00:00
for ( i = 0 ; i < moo - > sem_io_tuple_count ; i + + )
2017-02-12 18:59:03 +00:00
{
2017-12-25 18:35:23 +00:00
if ( moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_INPUT ] )
2020-11-27 05:13:02 +00:00
moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_INPUT ] = ( moo_oop_semaphore_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_INPUT ] ) ;
2017-12-25 18:35:23 +00:00
if ( moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_OUTPUT ] )
2020-11-27 05:13:02 +00:00
moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_OUTPUT ] = ( moo_oop_semaphore_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sem_io_tuple [ i ] . sem [ MOO_SEMAPHORE_IO_TYPE_OUTPUT ] ) ;
2017-02-12 18:59:03 +00:00
}
2020-11-27 05:13:02 +00:00
moo - > sem_gcfin = ( moo_oop_semaphore_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > sem_gcfin ) ;
2017-07-25 15:26:04 +00:00
2017-07-27 17:29:45 +00:00
for ( i = 0 ; i < moo - > proc_map_capa ; i + + )
{
2020-11-27 05:13:02 +00:00
moo - > proc_map [ i ] = moo_updateoopforgc ( moo , moo - > proc_map [ i ] ) ;
2017-07-27 17:29:45 +00:00
}
2019-08-14 16:24:39 +00:00
for ( i = 0 ; i < moo - > volat_count ; i + + )
2015-05-07 15:58:04 +00:00
{
2020-11-27 05:13:02 +00:00
* moo - > volat_stack [ i ] = moo_updateoopforgc ( moo , * moo - > volat_stack [ i ] ) ;
2015-05-25 17:10:49 +00:00
}
2017-01-09 09:54:49 +00:00
if ( moo - > initial_context )
2020-11-27 05:13:02 +00:00
moo - > initial_context = ( moo_oop_context_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > initial_context ) ;
2017-01-09 09:54:49 +00:00
if ( moo - > active_context )
2020-11-27 05:13:02 +00:00
moo - > active_context = ( moo_oop_context_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > active_context ) ;
2017-01-09 09:54:49 +00:00
if ( moo - > active_method )
2020-11-27 05:13:02 +00:00
moo - > active_method = ( moo_oop_method_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > active_method ) ;
2015-06-08 13:24:02 +00:00
2017-03-19 14:18:37 +00:00
moo_rbt_walk ( & moo - > modtab , call_module_gc , moo ) ;
2018-11-13 06:54:30 +00:00
for ( cb = moo - > evtcb_list ; cb ; cb = cb - > next )
2015-05-25 17:10:49 +00:00
{
2017-01-09 09:54:49 +00:00
if ( cb - > gc ) cb - > gc ( moo ) ;
2015-05-07 15:58:04 +00:00
}
2015-04-30 15:56:05 +00:00
2018-12-09 17:14:56 +00:00
/* scan the objects in the permspace in case an object there points to an object outside the permspace */
2020-11-27 05:13:02 +00:00
gc_ss_scan_space ( moo , ( moo_uint8_t * ) MOO_ALIGN ( ( moo_uintptr_t ) moo - > heap - > permspace . base , MOO_SIZEOF ( moo_oop_t ) ) , & moo - > heap - > permspace . ptr ) ;
2018-12-09 17:14:56 +00:00
2015-04-30 15:56:05 +00:00
/* scan the new heap to move referenced objects */
2020-11-27 05:13:02 +00:00
newspace_scan_ptr = gc_ss_scan_space ( moo , newspace_scan_ptr , & moo - > heap - > newspace . ptr ) ;
2015-04-30 15:56:05 +00:00
2017-07-27 08:32:16 +00:00
/* check finalizable objects registered and scan the heap again.
* symbol table compation is placed after this phase assuming that
* no symbol is added to be finalized . */
2018-12-08 15:35:26 +00:00
gcfin_count = move_finalizable_objects ( moo ) ;
2020-11-27 05:13:02 +00:00
newspace_scan_ptr = gc_ss_scan_space ( moo , newspace_scan_ptr , & moo - > heap - > newspace . ptr ) ;
2017-07-20 16:33:53 +00:00
2015-04-30 15:56:05 +00:00
/* 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 */
2019-01-08 10:05:27 +00:00
/*if (!moo->igniting) */ compact_symbol_table ( moo , old_nil ) ;
2015-04-30 15:56:05 +00:00
/* move the symbol table itself */
2020-11-27 05:13:02 +00:00
moo - > symtab = ( moo_oop_dic_t ) moo_updateoopforgc ( moo , ( moo_oop_t ) moo - > symtab ) ;
2015-04-30 15:56:05 +00:00
/* scan the new heap again from the end position of
* the previous scan to move referenced objects by
* the symbol table . */
2020-11-27 05:13:02 +00:00
newspace_scan_ptr = gc_ss_scan_space ( moo , newspace_scan_ptr , & moo - > heap - > newspace . ptr ) ;
2015-04-30 15:56:05 +00:00
2015-05-08 14:29:35 +00:00
/* the contents of the current heap is not needed any more.
* reset the upper bound to the base . don ' t forget to align the heap
2017-01-09 09:54:49 +00:00
* pointer to the OOP size . See moo_makeheap ( ) also */
2018-11-30 13:37:15 +00:00
moo - > heap - > curspace . ptr = ( moo_uint8_t * ) MOO_ALIGN ( ( ( moo_uintptr_t ) moo - > heap - > curspace . base ) , MOO_SIZEOF ( moo_oop_t ) ) ;
2015-05-08 14:29:35 +00:00
2015-04-30 15:56:05 +00:00
/* swap the current heap and old heap */
2018-11-30 13:37:15 +00:00
tmp = moo - > heap - > curspace ;
moo - > heap - > curspace = moo - > heap - > newspace ;
moo - > heap - > newspace = tmp ;
2015-04-30 15:56:05 +00:00
/*
2017-01-09 09:54:49 +00:00
if ( moo - > symtab & & MOO_LOG_ENABLED ( moo , MOO_LOG_GC | MOO_LOG_DEBUG ) )
2015-04-30 15:56:05 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oow_t index ;
moo_oop_oop_t buc ;
MOO_LOG0 ( moo , MOO_LOG_GC | MOO_LOG_DEBUG , " --------- SURVIVING SYMBOLS IN GC ---------- \n " ) ;
buc = ( moo_oop_oop_t ) moo - > symtab - > bucket ;
for ( index = 0 ; index < MOO_OBJ_GET_SIZE ( buc ) ; index + + )
2016-06-05 18:01:35 +00:00
{
2017-01-09 09:54:49 +00:00
if ( ( moo_oop_t ) buc - > slot [ index ] ! = moo - > _nil )
2016-06-05 18:01:35 +00:00
{
2017-01-09 09:54:49 +00:00
MOO_LOG1 ( moo , MOO_LOG_GC | MOO_LOG_DEBUG , " \t %O \n " , buc - > slot [ index ] ) ;
2016-06-05 18:01:35 +00:00
}
}
2017-01-09 09:54:49 +00:00
MOO_LOG0 ( moo , MOO_LOG_GC | MOO_LOG_DEBUG , " -------------------------------------------- \n " ) ;
2015-04-30 15:56:05 +00:00
}
*/
2016-06-05 18:01:35 +00:00
2018-12-23 08:33:52 +00:00
if ( moo - > active_method ) moo - > active_code = MOO_METHOD_GET_CODE_BYTE ( moo - > active_method ) ; /* update moo->active_code */
2017-07-27 08:32:16 +00:00
if ( gcfin_count > 0 ) moo - > sem_gcfin_sigreq = 1 ;
2016-06-05 18:01:35 +00:00
2019-06-22 14:22:58 +00:00
/* invalidate method cache. TODO: GCing entries on the method cache is also one way instead of full invalidation */
moo_clearmethodcache ( moo ) ;
2019-07-17 09:52:26 +00:00
2016-06-05 18:01:35 +00:00
/* TODO: include some gc statstics like number of live objects, gc performance, etc */
2017-01-09 09:54:49 +00:00
MOO_LOG4 ( moo , MOO_LOG_GC | MOO_LOG_INFO ,
2016-06-05 18:01:35 +00:00
" Finished GC curheap base %p ptr %p newheap base %p ptr %p \n " ,
2018-11-30 13:37:15 +00:00
moo - > heap - > curspace . base , moo - > heap - > curspace . ptr , moo - > heap - > newspace . base , moo - > heap - > newspace . ptr ) ;
2020-11-25 14:48:26 +00:00
}
2020-11-27 05:13:02 +00:00
void moo_gc ( moo_t * moo , int full )
2020-11-25 14:48:26 +00:00
{
# if defined(MOO_ENABLE_GC_MARK_SWEEP)
if ( moo - > gc_type = = MOO_GC_TYPE_MARK_SWEEP )
{
MOO_LOG1 ( moo , MOO_LOG_GC | MOO_LOG_INFO , " Starting GC (mark-sweep) - gci.bsz = %zu \n " , moo - > gci . bsz ) ;
2020-11-27 05:13:02 +00:00
2020-11-25 14:48:26 +00:00
moo - > gci . stack . len = 0 ;
/*moo->gci.stack.max = 0;*/
2020-11-27 05:13:02 +00:00
gc_ms_mark_roots ( moo ) ;
if ( ! full & & moo - > gci . lazy_sweep )
{
moo - > gci . ls . prev = MOO_NULL ;
moo - > gci . ls . curr = moo - > gci . b ;
}
else
{
gc_ms_sweep ( moo ) ;
}
2020-11-25 14:48:26 +00:00
MOO_LOG2 ( moo , MOO_LOG_GC | MOO_LOG_INFO , " Finished GC (mark-sweep) - gci.bsz = %zu, gci.stack.max %zu \n " , moo - > gci . bsz , moo - > gci . stack . max ) ;
}
else
# endif
{
2020-11-27 05:13:02 +00:00
gc_ss_scan_roots ( moo ) ;
2020-11-25 14:48:26 +00:00
}
}
2020-11-27 05:13:02 +00:00
moo_oop_t moo_updateoopforgc ( moo_t * moo , moo_oop_t oop )
2020-11-25 14:48:26 +00:00
{
# if defined(MOO_ENABLE_GC_MARK_SWEEP)
if ( moo - > gc_type = = MOO_GC_TYPE_MARK_SWEEP )
{
2020-11-27 05:13:02 +00:00
gc_ms_mark ( moo , oop ) ;
2020-11-25 14:48:26 +00:00
return oop ;
}
else
2020-10-17 07:02:44 +00:00
# endif
2020-11-25 14:48:26 +00:00
{
2020-11-27 05:13:02 +00:00
return gc_ss_move_oop ( moo , oop ) ;
2020-11-25 14:48:26 +00:00
}
2015-04-30 15:56:05 +00:00
}
2015-05-07 15:58:04 +00:00
2018-12-28 08:29:27 +00:00
void moo_pushvolat ( moo_t * moo , moo_oop_t * oop_ptr )
2015-05-07 15:58:04 +00:00
{
/* if you have too many temporaries pushed, something must be wrong.
* change your code not to exceede the stack limit */
2019-08-14 16:24:39 +00:00
MOO_ASSERT ( moo , moo - > volat_count < MOO_COUNTOF ( moo - > volat_stack ) ) ;
moo - > volat_stack [ moo - > volat_count + + ] = oop_ptr ;
2015-05-07 15:58:04 +00:00
}
2018-12-28 08:29:27 +00:00
void moo_popvolat ( moo_t * moo )
2015-05-07 15:58:04 +00:00
{
2019-08-14 16:24:39 +00:00
MOO_ASSERT ( moo , moo - > volat_count > 0 ) ;
moo - > volat_count - - ;
2015-05-07 15:58:04 +00:00
}
2018-12-28 08:29:27 +00:00
void moo_popvolats ( moo_t * moo , moo_oow_t count )
2015-05-07 15:58:04 +00:00
{
2019-08-14 16:24:39 +00:00
MOO_ASSERT ( moo , moo - > volat_count > = count ) ;
moo - > volat_count - = count ;
2015-05-07 15:58:04 +00:00
}
2015-10-30 15:36:37 +00:00
2017-01-09 09:54:49 +00:00
moo_oop_t moo_shallowcopy ( moo_t * moo , moo_oop_t oop )
2015-10-30 15:36:37 +00:00
{
2017-01-09 09:54:49 +00:00
if ( MOO_OOP_IS_POINTER ( oop ) & & MOO_OBJ_GET_CLASS ( oop ) ! = moo - > _symbol )
2015-10-30 15:36:37 +00:00
{
2017-01-09 09:54:49 +00:00
moo_oop_t z ;
moo_oow_t total_bytes ;
2015-10-30 15:36:37 +00:00
2019-09-22 16:26:30 +00:00
if ( MOO_OBJ_GET_FLAGS_UNCOPYABLE ( oop ) )
2019-09-20 09:27:24 +00:00
{
/* TOOD: should i disallow this or return without copying? */
2019-09-22 16:26:30 +00:00
moo_seterrbfmt ( moo , MOO_EPERM , " uncopyable object " ) ;
2019-09-20 09:27:24 +00:00
return MOO_NULL ;
}
2015-10-30 15:36:37 +00:00
2019-09-20 09:27:24 +00:00
total_bytes = MOO_SIZEOF ( moo_obj_t ) + moo_getobjpayloadbytes ( moo , oop ) ;
2019-09-30 05:23:04 +00:00
if ( MOO_OBJ_GET_FLAGS_HASH ( oop ) = = MOO_OBJ_FLAGS_HASH_STORED )
2019-09-23 06:42:47 +00:00
{
/* exclude the hash value field from copying */
total_bytes - = MOO_SIZEOF ( moo_oow_t ) ;
}
2019-09-16 14:16:55 +00:00
2018-12-28 08:29:27 +00:00
moo_pushvolat ( moo , & oop ) ;
2018-12-10 13:34:31 +00:00
z = ( moo_oop_t ) moo_allocbytes ( moo , total_bytes ) ;
2018-12-28 08:29:27 +00:00
moo_popvolat ( moo ) ;
2015-10-30 15:36:37 +00:00
2017-01-09 09:54:49 +00:00
MOO_MEMCPY ( z , oop , total_bytes ) ;
2019-06-19 09:21:28 +00:00
MOO_OBJ_SET_FLAGS_RDONLY ( z , 0 ) ; /* a copied object is not read-only */
2019-09-23 06:42:47 +00:00
MOO_OBJ_SET_FLAGS_HASH ( z , 0 ) ; /* no hash field */
2019-09-16 14:16:55 +00:00
return z ;
2015-10-30 15:36:37 +00:00
}
return oop ;
}
2017-07-20 16:33:53 +00:00
int moo_regfinalizable ( moo_t * moo , moo_oop_t oop )
{
2017-07-21 16:54:43 +00:00
moo_finalizable_t * x ;
if ( ! MOO_OOP_IS_POINTER ( oop ) | | ( MOO_OBJ_GET_FLAGS_GCFIN ( oop ) & ( MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED ) ) )
2017-07-20 16:33:53 +00:00
{
moo_seterrnum ( moo , MOO_EINVAL ) ;
return - 1 ;
}
2018-02-26 15:30:38 +00:00
x = ( moo_finalizable_t * ) moo_allocmem ( moo , MOO_SIZEOF ( * x ) ) ;
2017-07-20 16:33:53 +00:00
if ( ! x ) return - 1 ;
MOO_OBJ_SET_FLAGS_GCFIN ( oop , MOO_GCFIN_FINALIZABLE ) ;
x - > oop = oop ;
MOO_APPEND_TO_LIST ( & moo - > finalizable , x ) ;
return 0 ;
}
int moo_deregfinalizable ( moo_t * moo , moo_oop_t oop )
{
2017-07-21 16:54:43 +00:00
moo_finalizable_t * x ;
2017-07-20 16:33:53 +00:00
2017-07-21 16:54:43 +00:00
if ( ! MOO_OOP_IS_POINTER ( oop ) | | ( ( MOO_OBJ_GET_FLAGS_GCFIN ( oop ) & ( MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED ) ) ! = MOO_GCFIN_FINALIZABLE ) )
2017-07-20 16:33:53 +00:00
{
moo_seterrnum ( moo , MOO_EINVAL ) ;
return - 1 ;
}
x = moo - > finalizable . first ;
while ( x )
{
if ( x - > oop = = oop )
{
MOO_OBJ_SET_FLAGS_GCFIN ( oop , ( MOO_OBJ_GET_FLAGS_GCFIN ( oop ) & ~ MOO_GCFIN_FINALIZABLE ) ) ;
MOO_DELETE_FROM_LIST ( & moo - > finalizable , x ) ;
2018-05-16 08:03:34 +00:00
moo_freemem ( moo , x ) ;
2017-07-20 16:33:53 +00:00
return 0 ;
}
2018-05-16 08:03:34 +00:00
x = x - > next ;
2017-07-20 16:33:53 +00:00
}
moo_seterrnum ( moo , MOO_ENOENT ) ;
return - 1 ;
}
2018-05-16 08:03:34 +00:00
void moo_deregallfinalizables ( moo_t * moo )
{
moo_finalizable_t * x , * nx ;
x = moo - > finalizable . first ;
while ( x )
{
nx = x - > next ;
MOO_OBJ_SET_FLAGS_GCFIN ( x - > oop , ( MOO_OBJ_GET_FLAGS_GCFIN ( x - > oop ) & ~ MOO_GCFIN_FINALIZABLE ) ) ;
MOO_DELETE_FROM_LIST ( & moo - > finalizable , x ) ;
moo_freemem ( moo , x ) ;
x = nx ;
}
MOO_ASSERT ( moo , moo - > finalizable . first = = MOO_NULL ) ;
MOO_ASSERT ( moo , moo - > finalizable . last = = MOO_NULL ) ;
}
2017-07-27 08:32:16 +00:00
static moo_oow_t move_finalizable_objects ( moo_t * moo )
2017-07-20 16:33:53 +00:00
{
2017-07-21 16:54:43 +00:00
moo_finalizable_t * x , * y ;
2017-07-27 08:32:16 +00:00
moo_oow_t count = 0 ;
2017-07-20 16:33:53 +00:00
for ( x = moo - > collectable . first ; x ; x = x - > next )
{
2017-07-21 16:54:43 +00:00
MOO_ASSERT ( moo , ( MOO_OBJ_GET_FLAGS_GCFIN ( x - > oop ) & ( MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED ) ) = = MOO_GCFIN_FINALIZABLE ) ;
2020-11-27 05:13:02 +00:00
x - > oop = moo_updateoopforgc ( moo , x - > oop ) ;
2017-07-20 16:33:53 +00:00
}
for ( x = moo - > finalizable . first ; x ; )
{
y = x - > next ;
2017-07-21 16:54:43 +00:00
MOO_ASSERT ( moo , ( MOO_OBJ_GET_FLAGS_GCFIN ( x - > oop ) & ( MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED ) ) = = MOO_GCFIN_FINALIZABLE ) ;
2017-07-20 16:33:53 +00:00
if ( ! MOO_OBJ_GET_FLAGS_MOVED ( x - > oop ) )
{
2017-07-21 16:54:43 +00:00
/* the object has not been moved. it means this object is not reachable
* from the root except this finalizable list . this object would be
* garbage if not for finalizatin . it ' s almost collectable . but it
* will survive this cycle for finalization .
*
* if garbages consist of finalizable objects only , GC should fail miserably .
* however this is quite unlikely because some key objects for VM execution
* like context objects doesn ' t require finalization . */
2017-07-20 16:33:53 +00:00
2020-11-27 05:13:02 +00:00
x - > oop = moo_updateoopforgc ( moo , x - > oop ) ;
2017-07-20 16:33:53 +00:00
/* remove it from the finalizable list */
MOO_DELETE_FROM_LIST ( & moo - > finalizable , x ) ;
/* add it to the collectable list */
MOO_APPEND_TO_LIST ( & moo - > collectable , x ) ;
2017-07-27 08:32:16 +00:00
count + + ;
2017-07-20 16:33:53 +00:00
}
else
{
2020-11-27 05:13:02 +00:00
x - > oop = moo_updateoopforgc ( moo , x - > oop ) ;
2017-07-20 16:33:53 +00:00
}
x = y ;
}
2017-07-27 08:32:16 +00:00
return count ;
2017-07-20 16:33:53 +00:00
}