wip - full oop - added spec and selfspec to the class struct
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
hyung-hwan 2024-03-06 07:51:29 +09:00
parent 7a15fbc3d1
commit 874d0c7962
4 changed files with 85 additions and 138 deletions

View File

@ -98,7 +98,7 @@ do { | k | set k 20; printf "k=%d\n" k; };
```
(defclass T
:: | A B C | ; class variables
:: | A B C | ## class variables
(printf "initializing....\n")
@ -142,7 +142,7 @@ do { | k | set k 20; printf "k=%d\n" k; };
(defun x(a b ... :: x y z)
|i|
; (printf "VA_COUNT(x) = %d\n" (va-count))
## (printf "VA_COUNT(x) = %d\n" (va-count))
(set x "xxx")
(set y "yyy")
(set z "zzz")

191
lib/gc.c
View File

@ -65,71 +65,6 @@ static struct
/* ========================================================================= */
static struct
{
const char* name;
hcl_oow_t c_offset; /* class offset */
hcl_oow_t sc_offset; /* superclass offset */
hcl_oow_t nivars;
hcl_oow_t ncvars;
} kctab[] = {
{ "Apex",
HCL_OFFSETOF(hcl_t, c_apex),
HCL_TYPE_MAX(hcl_oow_t),
0, 0 },
{ "Object",
HCL_OFFSETOF(hcl_t, c_object),
HCL_OFFSETOF(hcl_t, c_apex),
0, 0 },
{ "UndefinedObject",
HCL_OFFSETOF(hcl_t, c_undefobj),
HCL_OFFSETOF(hcl_t, c_apex),
0, 0 },
{ "Class",
HCL_OFFSETOF(hcl_t, c_class),
HCL_OFFSETOF(hcl_t, c_object),
HCL_CLASS_NAMED_INSTVARS, 0 },
{ "String",
HCL_OFFSETOF(hcl_t, c_string),
HCL_OFFSETOF(hcl_t, c_object),
0, 0 },
{ "Symbol",
HCL_OFFSETOF(hcl_t, c_symbol),
HCL_OFFSETOF(hcl_t, c_string),
0, 0 },
#if 0
{ "Boolean",
HCL_OFFSETOF(hcl_t, c_boolean),
HCL_OFFSETOF(hcl_t, c_object),
0, 0 },
{ "True",
HCL_OFFSETOF(hcl_t, c_true),
HCL_OFFSETOF(hcl_t, c_boolean),
0, 0 },
{ "False",
HCL_OFFSETOF(hcl_t, c_false),
HCL_OFFSETOF(hcl_t, c_boolean),
0, 0 },
#endif
{ "System",
HCL_OFFSETOF(hcl_t, c_system),
HCL_OFFSETOF(hcl_t, c_object),
0, 0 },
};
/* ========================================================================= */
/*
* Apex......................
* ^ ^ ^ : .......
@ -1199,10 +1134,6 @@ hcl_oop_t hcl_shallowcopy (hcl_t* hcl, hcl_oop_t oop)
/* ========================================================================= */
#if 0
static hcl_oow_t move_finalizable_objects (hcl_t* hcl);
/* -----------------------------------------------------------------------
* BOOTSTRAPPER
* ----------------------------------------------------------------------- */
@ -1210,20 +1141,24 @@ static hcl_oow_t move_finalizable_objects (hcl_t* hcl);
static hcl_oop_class_t alloc_kernel_class (hcl_t* hcl, int class_flags, hcl_oow_t num_classvars, hcl_oow_t spec)
{
hcl_oop_class_t c;
#if 0
hcl_ooi_t cspec;
#endif
c = (hcl_oop_class_t)hcl_allocoopobj(hcl, HCL_CLASS_NAMED_INSTVARS + num_classvars);
c = (hcl_oop_class_t)hcl_allocoopobj(hcl, HCL_BRAND_CLASS, HCL_CLASS_NAMED_INSTVARS + num_classvars);
if (!c) return HCL_NULL;
HCL_OBJ_SET_FLAGS_KERNEL (c, HCL_OBJ_FLAGS_KERNEL_IMMATURE);
#if 0 /* TODO extend the flags and uncomment this part */
cspec = kernel_classes[KCI_CLASS].class_spec_flags;
if (HCL_CLASS_SPEC_IS_IMMUTABLE(cspec)) HCL_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 (HCL_CLASS_SPEC_IS_UNCOPYABLE(cspec)) HCL_OBJ_SET_FLAGS_UNCOPYABLE (c, 1); /* class itself is uncopyable */
#endif
HCL_OBJ_SET_CLASS (c, (hcl_oop_t)hcl->_class);
c->spec = HCL_SHCLI_TO_OOP(spec);
c->selfspec = HCL_SHCLI_TO_OOP(HCL_CLASS_SELFSPEC_MAKE(num_classvars, 0, class_flags));
HCL_OBJ_SET_CLASS (c, (hcl_oop_t)hcl->c_class);
c->spec = HCL_SMOOI_TO_OOP(spec);
c->selfspec = HCL_SMOOI_TO_OOP(HCL_CLASS_SELFSPEC_MAKE(num_classvars, 0, class_flags));
return c;
}
@ -1239,22 +1174,22 @@ static int ignite_1 (hcl_t* hcl)
HCL_ASSERT (hcl, hcl->_nil != HCL_NULL);
HCL_ASSERT (hcl, HCL_OBJ_GET_CLASS(hcl->_nil) == HCL_NULL);
HCL_ASSERT (hcl, hcl->_class == HCL_NULL);
HCL_ASSERT (hcl, hcl->c_class == HCL_NULL);
/* --------------------------------------------------------------
* Class
* The instance of Class can have indexed instance variables
* which are actually class variables.
* -------------------------------------------------------------- */
hcl->_class = alloc_kernel_class(
hcl->c_class = alloc_kernel_class(
hcl, kernel_classes[KCI_CLASS].class_flags,
kernel_classes[KCI_CLASS].class_num_classvars,
HCL_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));
if (!hcl->_class) return -1;
if (!hcl->c_class) return -1;
HCL_ASSERT (hcl, HCL_OBJ_GET_CLASS(hcl->_class) == HCL_NULL);
HCL_OBJ_SET_CLASS (hcl->_class, (hcl_oop_t)hcl->_class);
HCL_ASSERT (hcl, HCL_OBJ_GET_CLASS(hcl->c_class) == HCL_NULL);
HCL_OBJ_SET_CLASS (hcl->c_class, (hcl_oop_t)hcl->c_class);
for (i = 0; i < HCL_COUNTOF(kernel_classes); i++)
{
@ -1272,16 +1207,18 @@ static int ignite_1 (hcl_t* hcl)
*(hcl_oop_class_t*)((hcl_uint8_t*)hcl + kernel_classes[i].offset) = tmp;
}
HCL_OBJ_SET_CLASS (hcl->_nil, (hcl_oop_t)hcl->_undefined_object);
HCL_OBJ_SET_CLASS (hcl->_nil, (hcl_oop_t)hcl->c_undefobj);
#if 0
/* 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. */
hcl->_method->trsize = HCL_SHCLI_TO_OOP(0);
hcl->_method->trgc = HCL_SMPTR_TO_OOP(0);
hcl->c_method->trsize = HCL_SMOOI_TO_OOP(0);
hcl->c_method->trgc = HCL_SMPTR_TO_OOP(0);
#endif
return 0;
}
@ -1289,13 +1226,16 @@ static int ignite_1 (hcl_t* hcl)
static int ignite_2 (hcl_t* hcl)
{
hcl_oop_t tmp;
#if 0
int old_igniting = hcl->igniting;
#endif
/* Create 'true' and 'false objects */
hcl->_true = hcl_instantiate(hcl, hcl->_true_class, HCL_NULL, 0);
hcl->_false = hcl_instantiate(hcl, hcl->_false_class, HCL_NULL, 0);
if (HCL_UNLIKELY(!hcl->_true) || HCL_UNLIKELY(!hcl->_false)) return -1;
hcl->_true = hcl_instantiate(hcl, hcl->c_true, HCL_NULL, 0);
hcl->_false = hcl_instantiate(hcl, hcl->c_false, HCL_NULL, 0);
if (HCL_UNLIKELY(!hcl->c_true) || HCL_UNLIKELY(!hcl->c_false)) return -1;
#if 0
/* Prevent the object instations in the permspace.
*
* 1. The symbol table is big and it may resize after ignition.
@ -1314,51 +1254,57 @@ static int ignite_2 (hcl_t* hcl)
* For now, let's just allocate the symbol table and the system dictionary
* in the normal space */
hcl->igniting = 0;
#endif
/* Create the symbol table */
tmp = hcl_instantiate(hcl, hcl->_symbol_table, HCL_NULL, 0);
tmp = hcl_instantiate(hcl, hcl->c_symtab, HCL_NULL, 0);
if (HCL_UNLIKELY(!tmp)) return -1;
hcl->symtab = (hcl_oop_dic_t)tmp;
hcl->symtab->tally = HCL_SHCLI_TO_OOP(0);
hcl->symtab->tally = HCL_SMOOI_TO_OOP(0);
/* It's important to assign the result of hcl_instantiate() to a temporary
* variable first and then assign it to hcl->symtab->bucket.
* The pointer 'hcl->symtab; can change in hcl_instantiate() and the
* target address of assignment may get set before hcl_instantiate()
* is called. */
tmp = hcl_instantiate(hcl, hcl->_array, HCL_NULL, hcl->option.dfl_symtab_size);
if (!tmp) return -1;
tmp = hcl_instantiate(hcl, hcl->c_array, HCL_NULL, hcl->option.dfl_symtab_size);
if (HCL_UNLIKELY(!tmp)) return -1;
hcl->symtab->bucket = (hcl_oop_oop_t)tmp;
#if 0
/* Create the system dictionary */
tmp = (hcl_oop_t)hcl_makensdic(hcl, hcl->_namespace, hcl->option.dfl_sysdic_size);
if (!tmp) return -1;
hcl->sysdic = (hcl_oop_nsdic_t)tmp;
hcl->igniting = old_igniting; /* back to the permspace */
#endif
/* Create a nil process used to simplify nil check in GC.
* only accessible by VM. not exported via the global dictionary. */
tmp = (hcl_oop_t)hcl_instantiate(hcl, hcl->_process, HCL_NULL, 0);
if (!tmp) return -1;
tmp = (hcl_oop_t)hcl_instantiate(hcl, hcl->c_process, HCL_NULL, 0);
if (HCL_UNLIKELY(!tmp)) return -1;
hcl->nil_process = (hcl_oop_process_t)tmp;
hcl->nil_process->sp = HCL_SHCLI_TO_OOP(-1);
hcl->nil_process->id = HCL_SHCLI_TO_OOP(-1);
hcl->nil_process->sp = HCL_SMOOI_TO_OOP(-1);
hcl->nil_process->id = HCL_SMOOI_TO_OOP(-1);
#if 0
hcl->nil_process->perr = HCL_ERROR_TO_OOP(HCL_ENOERR);
hcl->nil_process->perrmsg = hcl->_nil;
#endif
/* Create a process scheduler */
tmp = (hcl_oop_t)hcl_instantiate(hcl, hcl->_process_scheduler, HCL_NULL, 0);
if (!tmp) return -1;
tmp = (hcl_oop_t)hcl_instantiate(hcl, hcl->c_process_scheduler, HCL_NULL, 0);
if (HCL_UNLIKELY(!tmp)) return -1;
hcl->processor = (hcl_oop_process_scheduler_t)tmp;
hcl->processor->active = hcl->nil_process;
hcl->processor->total_count = HCL_SHCLI_TO_OOP(0);
hcl->processor->runnable.count = HCL_SHCLI_TO_OOP(0);
hcl->processor->suspended.count = HCL_SHCLI_TO_OOP(0);
hcl->processor->total_count = HCL_SMOOI_TO_OOP(0);
hcl->processor->runnable.count = HCL_SMOOI_TO_OOP(0);
hcl->processor->suspended.count = HCL_SMOOI_TO_OOP(0);
return 0;
}
#if 0
static int ignite_3 (hcl_t* hcl)
{
/* Register kernel classes manually created so far to the system dictionary */
@ -1420,23 +1366,6 @@ static int ignite_3 (hcl_t* hcl)
return 0;
}
struct hcl_class_t
{
HCL_OBJ_HEADER;
hcl_oop_t mdic; /* method dictionary. nil or a dictionary object */
hcl_oop_t superclass;
hcl_oop_t nivars; /* smooi. */
hcl_oop_t ncvars; /* smooi. */
hcl_oop_t nivars_super; /* smooi */
hcl_oop_char_t ivarnames;
hcl_oop_char_t cvarnames;
/* indexed part afterwards - not included in HCL_CLASS_NAMED_INSTVARS */
hcl_oop_t cvar[1]; /* class variables. */
};
#endif
static int make_kernel_classes (hcl_t* hcl)
@ -1447,29 +1376,29 @@ static int make_kernel_classes (hcl_t* hcl)
/* make_kernel_classes() creates a chain of classes for initial bootstrapping.
* when the objects are loaded from an image file, this function is skipped */
#if 0
/* create class objects */
for (i = 0; i < HCL_COUNTOF(kctab); i++)
{
if (kctab[i].c_offset >= HCL_SIZEOF(*hcl)) continue;
hcl->igniting = 1;
hcl->_nil = moo_allocbytes(hcl, MOO_SIZEOF(hcl_obj_t));
if (HCL_UNLIKELY(!hcl->_nil)) goto oops;
c = (hcl_oop_class_t)hcl_makeclass(hcl, hcl->_nil, nivars, ncvars, "ivars_str", "cvars_str");
if (HCL_UNLIKELY(!c)) return -1;
*(hcl_oop_class_t*)((hcl_uint8_t*)hcl + kctab[i].c_offset) = c;
}
/* update the superclass field */
for (i = 0; i < HCL_COUNTOF(kctab); i++)
{
if (kctab[i].sc_offset >= HCL_SIZEOF(*hcl)) continue;
c = *(hcl_oop_class_t*)((hcl_uint8_t*)hcl + kctab[i].c_offset);
c->superclass = *(hcl_oop_t*)((hcl_uint8_t*)hcl + kctab[i].sc_offset);
}
hcl->_nil->_flags = HCL_OBJ_MAKE_FLAGS(HCL_OBJ_TYPE_OOP, HCL_SIZEOF(moo_oop_t), 0, 1, hcl->igniting, 0, 0, 0, 0, 0);
hcl->_nil->_size = 0;
#endif
if (ignite_1(hcl) <= -1 || ignite_2(hcl) <= -1 /*|| ignite_3(hcl)*/) goto oops;
#if 0
moo->igniting = 0;
#endif
return 0;
oops:
#if 0
moo->igniting = 0;
#endif
return -1;
}
int hcl_ignite (hcl_t* hcl, hcl_oow_t heapsize)

View File

@ -369,6 +369,16 @@ typedef enum hcl_obj_type_t hcl_obj_type_t;
#define HCL_OBJ_FLAGS_SYNCODE_BITS 5
#define HCL_OBJ_FLAGS_BRAND_BITS 6
/*
#define HCL_OBJ_FLAGS_PERM_BITS 1
#define HCL_OBJ_FLAGS_MOVED_BITS 2
#define HCL_OBJ_FLAGS_PROC_BITS 2
#define HCL_OBJ_FLAGS_RDONLY_BITS 1
#define HCL_OBJ_FLAGS_GCFIN_BITS 4
#define HCL_OBJ_FLAGS_TRAILER_BITS 1
#define HCL_OBJ_FLAGS_HASH_BITS 2
#define HCL_OBJ_FLAGS_UNCOPYABLE_BITS 1
*/
#define HCL_OBJ_FLAGS_TYPE_SHIFT (HCL_OBJ_FLAGS_UNIT_BITS + HCL_OBJ_FLAGS_UNIT_SHIFT)
#define HCL_OBJ_FLAGS_UNIT_SHIFT (HCL_OBJ_FLAGS_EXTRA_BITS + HCL_OBJ_FLAGS_EXTRA_SHIFT)
@ -430,6 +440,10 @@ typedef enum hcl_obj_type_t hcl_obj_type_t;
(((hcl_oow_t)(b)) << HCL_OBJ_FLAGS_BRAND_SHIFT) \
)
#define HCL_OBJ_FLAGS_KERNEL_USER 0 /* not a kernel object */
#define HCL_OBJ_FLAGS_KERNEL_IMMATURE 1 /* incomplete kernel object. defined in gc.c for bootstrapping. but no complete class definition has been read */
#define HCL_OBJ_FLAGS_KERNEL_MATURE 2 /* kernel object with its full class defintion read in */
#define HCL_OBJ_HEADER \
hcl_oow_t _flags; \
hcl_oow_t _size; \
@ -836,7 +850,7 @@ struct hcl_process_scheduler_t
};
#define HCL_CLASS_NAMED_INSTVARS 7
#define HCL_CLASS_NAMED_INSTVARS 9
typedef struct hcl_class_t hcl_class_t;
typedef struct hcl_class_t* hcl_oop_class_t;
struct hcl_class_t
@ -845,10 +859,13 @@ struct hcl_class_t
hcl_oop_t mdic; /* method dictionary. nil or a dictionary object */
hcl_oop_t spec; /* SmallInteger. instance specification */
hcl_oop_t selfspec; /* SmallInteger. specification of the class object itself */
hcl_oop_t superclass;
hcl_oop_t nivars; /* smooi. */
hcl_oop_t ncvars; /* smooi. */
hcl_oop_t nivars_super; /* smooi */
hcl_oop_t nivars; /* SmallInteger. */
hcl_oop_t ncvars; /* SmallInteger. */
hcl_oop_t nivars_super; /* SmallInteger */
hcl_oop_char_t ivarnames;
hcl_oop_char_t cvarnames;
@ -1982,7 +1999,6 @@ enum hcl_syncode_t
HCL_SYNCODE_TRY,
HCL_SYNCODE_UNTIL,
HCL_SYNCODE_WHILE
};
typedef enum hcl_syncode_t hcl_syncode_t;

View File

@ -416,6 +416,8 @@ hcl_oop_t hcl_makeclass (hcl_t* hcl, hcl_oop_t superclass, hcl_ooi_t nivars, hcl
return HCL_NULL;
}
c->spec = HCL_SMOOI_TO_OOP(0); /* TODO: fix this */
c->selfspec = HCL_SMOOI_TO_OOP(0); /* TODO: fix this */
c->superclass = superclass;
c->nivars = HCL_SMOOI_TO_OOP(nivars);
c->ncvars = HCL_SMOOI_TO_OOP(ncvars);