diff --git a/stix/lib/obj.c b/stix/lib/obj.c index 59701dd..f22b53a 100644 --- a/stix/lib/obj.c +++ b/stix/lib/obj.c @@ -148,8 +148,8 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, if (indexed_type == STIX_OBJ_TYPE_OOP) { - if (named_instvar > STIX_MAX_NAMED_INSTVAR || - vlen > STIX_MAX_INDEXED_COUNT(named_instvar)) + if (named_instvar > STIX_MAX_NAMED_INSTVARS || + vlen > STIX_MAX_INDEXED_INSTVARS(named_instvar)) { goto einval; } @@ -167,7 +167,7 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr, indexed_type = STIX_OBJ_TYPE_OOP; vlen = 0; - if (named_instvar > STIX_MAX_NAMED_INSTVAR) goto einval; + if (named_instvar > STIX_MAX_NAMED_INSTVARS) goto einval; } switch (indexed_type) diff --git a/stix/lib/stix-prv.h b/stix/lib/stix-prv.h index af9dfe8..06f575d 100644 --- a/stix/lib/stix-prv.h +++ b/stix/lib/stix-prv.h @@ -49,59 +49,96 @@ struct stix_class_t { STIX_OBJ_HEADER; - stix_oow_t spec; - stix_oop_oop_t methods; - stix_oop_oop_t superclass; - stix_oop_char_t name; - stix_oop_char_t instvars; - stix_oop_char_t classvars; - /* variable part afterwards */ + stix_oow_t spec; /* SmallInteger */ + stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */ + stix_oop_oop_t classmthds; /* class methods, MethodDictionary */ + stix_oop_oop_t superclass; /* Another class */ + + stix_oop_char_t name; /* Symbol */ + stix_oop_char_t instvars; /* String or Array? */ + stix_oop_char_t classvars; /* String or Array? */ + + /* indexed part afterwards */ }; + typedef struct stix_class_t stix_class_t; typedef struct stix_class_t* stix_oop_class_t; /* * The spec field of a class object encodes the number of the fixed part - * and the type of the variable part. The fixed part is the number of - * instance variables. The variable part can be specified when the object - * is instantiated if it is variadic. + * and the type of the indexed part. The fixed part is the number of + * named instance variables. If the spec of a class is indexed, the object + * of the class can be i nstantiated with the size of the indexed part. * - * indexed_type is one of the #stix_obj_type_t enumerators. + * For example, on a platform where sizeof(stix_oow_t) is 4, + * the layout of the spec field of a class as an OOP value looks like this: + * + * 31 10 9 8 7 6 5 4 3 2 1 0 + * |number of named instance variables|indexed-type|indexability|oop-tag| + * + * the number of named instance variables is stored in high 23 bits. + * the indexed type takes up bit 3 to bit 8. And the indexability is + * stored in bit 2. * * The maximum number of named(fixed) instance variables for a class is: - * 2 ^ (BITS-IN-OOW - STIX_OBJ_TYPE_BITS - 1) + * 2 ^ ((BITS-IN-OOW - STIX_OOP_TAG_BITS) - STIX_OBJ_TYPE_BITS - 1) - 1 + * + * STIX_OOP_TAG_BITS are decremented from the number of bits in OOW because + * the spec field is always encoded as a small integer. * * The number of named instance variables can be greater than 0 if the * class spec is not indexed or if it's a pointer indexed class * (indexed_type == STIX_OBJ_TYPE_OOP) + * + * indexed_type is one of the #stix_obj_type_t enumerators. + */ + +/* + * The STIX_CLASS_SPEC_MAKE() macro creates a class spec value. + * _class->spec = STIX_OOP_FROM_SMINT(STIX_CLASS_SPEC_MAKE(0, 1, STIX_OBJ_TYPE_CHAR)); */ #define STIX_CLASS_SPEC_MAKE(named_instvar,is_indexed,indexed_type) ( \ - (((stix_oow_t)(named_instvar)) << (STIX_OBJ_TYPE_BITS + 1)) | \ + (((stix_oow_t)(named_instvar)) << (STIX_OBJ_FLAGS_TYPE_BITS + 1)) | \ (((stix_oow_t)(indexed_type)) << 1) | (((stix_oow_t)is_indexed) & 1) ) -/* what is the number of named instance variables? */ -#define STIX_CLASS_SPEC_NAMED_INSTVAR(spec) ((spec) >> STIX_OBJ_FLAGS_TYPE_BITS) +/* what is the number of named instance variables? + * STIX_CLASS_SPEC_NAMED_INSTVAR(STIX_OOP_TO_SMINT(_class->spec)) + */ +#define STIX_CLASS_SPEC_NAMED_INSTVAR(spec) \ + (((stix_oow_t)(spec)) >> (STIX_OBJ_FLAGS_TYPE_BITS + 1)) /* is it a user-indexable class? * all objects can be indexed with basicAt:. * this indicates if an object can be instantiated with a dynamic size * (new: size) and and can be indexed with at:. */ -#define STIX_CLASS_SPEC_IS_INDEXED(spec) ((spec) & 1) +#define STIX_CLASS_SPEC_IS_INDEXED(spec) (((stix_oow_t)(spec)) & 1) /* if so, what is the indexing type? character? pointer? etc? */ -#define STIX_CLASS_SPEC_INDEXED_TYPE(spec) ((spec) & (STIX_LBMASK(stix_oow_t, STIX_OBJ_FLAGS_TYPE_BITS) << 1)) +#define STIX_CLASS_SPEC_INDEXED_TYPE(spec) \ + ((((stix_oow_t)(spec)) >> 1) & STIX_LBMASK(stix_oow_t, STIX_OBJ_FLAGS_TYPE_BITS)) +/* What is the maximum number of named instance variables? + * 2 ^ ((BITS-IN-OOW - STIX_OOP_TAG_BITS) - STIX_OBJ_TYPE_BITS - 1) - 1 + * This limit is set because the number must be encoded into the spec field + * of the class with limited number of bits assigned to the number of + * named instance variables. + */ +#define STIX_MAX_NAMED_INSTVARS \ + STIX_BITS_MAX(stix_oow_t, STIX_OOW_BITS - STIX_OOP_TAG_BITS - (STIX_OBJ_FLAGS_TYPE_BITS + 1)) -/* 2 ^ (BITS-IN-OOW - STIX_OBJ_TYPE_BITS - 1) */ -#define STIX_MAX_NAMED_INSTVAR ((stix_oow_t)2 << (STIX_SIZEOF(stix_oow_t) * 8 - (STIX_OBJ_FLAGS_TYPE_BITS + 1) - 1)) /* Given the number of named instance variables, what is the maximum number - * of indexed slots? */ -#define STIX_MAX_INDEXED_COUNT(named_instvar) ((~(stix_oow_t)0) - named_instvar) + * of indexed instance variables? The number of indexed instance variables + * is not stored in the spec field of the class. It only affects the actual + * size of an object(obj->_size) selectively combined with the number of + * named instance variables. So it's the maximum value of obj->_size minus + * the number of named instance variables. + */ +#define STIX_MAX_INDEXED_INSTVARS(named_instvar) ((~(stix_oow_t)0) - named_instvar) + -/* VM-level macros */ #define STIX_CLASSOF(stix,oop) \ (STIX_OOP_IS_NUMERIC(oop)? \ ((stix_oop_t)(stix)->cc.numeric[((stix_oow_t)oop&3)-1]): \ diff --git a/stix/lib/stix.h b/stix/lib/stix.h index 8da9187..70a3ca8 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -69,10 +69,21 @@ typedef unsigned short int stix_char_t; /* TODO ... wchar_t??? */ /* get 'length' bits starting from the bit at the 'offset' */ #define STIX_GETBITS(type,value,offset,length) \ - (((value) >> (offset)) & STIX_LBMASK(type,length)) + ((((type)(value)) >> (offset)) & STIX_LBMASK(type,length)) #define STIX_SETBITS(type,value,offset,length,bits) \ - (value = ((value) | (((bits) & STIX_LBMASK(type,length)) << (offset)))) + (value = (((type)(value)) | (((bits) & STIX_LBMASK(type,length)) << (offset)))) + + +/** + * The STIX_BITS_MAX() macros calculates the maximum value that the 'nbits' + * bits of an unsigned integer of the given 'type' can hold. + * \code + * printf ("%u", STIX_BITS_MAX(unsigned int, 5)); + * \endcode + */ +/*#define STIX_BITS_MAX(type,nbits) ((((type)1) << (nbits)) - 1)*/ +#define STIX_BITS_MAX(type,nbits) ((~(type)0) >> (STIX_SIZEOF(type) * 8 - (nbits))) typedef struct stix_mmgr_t stix_mmgr_t; @@ -206,6 +217,9 @@ typedef struct stix_obj_char_t* stix_oop_char_t; typedef struct stix_obj_uint8_t* stix_oop_uint8_t; typedef struct stix_obj_uint16_t* stix_oop_uint16_t; +#define STIX_OOW_BITS (STIX_SIZEOF(stix_oow_t) * 8) +#define STIX_OOP_BITS (STIX_SIZEOF(stix_oop_t) * 8) + /* * The Smalltalk-80 Bytecodes * Range Bits Function @@ -433,19 +447,19 @@ struct stix_t * of a real OOP are always 0s. */ -#define STIX_OOP_TYPE_BITS 2 -#define STIX_OOP_TYPE_SMINT 1 -#define STIX_OOP_TYPE_CHAR 2 +#define STIX_OOP_TAG_BITS 2 +#define STIX_OOP_TAG_SMINT 1 +#define STIX_OOP_TAG_CHAR 2 -#define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TYPE_SMINT | STIX_OOP_TYPE_CHAR)) +#define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TAG_SMINT | STIX_OOP_TAG_CHAR)) #define STIX_OOP_IS_POINTER(oop) (!STIX_OOP_IS_NUMERIC(oop)) -#define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TYPE_SMINT) -#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TYPE_CHAR) -#define STIX_OOP_FROM_SMINT(num) ((stix_oop_t)(((num) << STIX_OOP_TYPE_BITS) | STIX_OOP_TYPE_SMINT)) -#define STIX_OOP_TO_SMINT(oop) (((stix_oow_t)oop) >> STIX_OOP_TYPE_BITS) -#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)(((num) << STIX_OOP_TYPE_BITS) | STIX_OOP_TYPE_CHAR)) -#define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TYPE_BITS) +#define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_SMINT) +#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR) +#define STIX_OOP_FROM_SMINT(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_SMINT)) +#define STIX_OOP_TO_SMINT(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS) +#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR)) +#define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS) /* * Object structure @@ -506,7 +520,7 @@ typedef enum stix_obj_type_t stix_obj_type_t; * Therefore, i've dropped the idea. * ------------------------------------------------------------------------- */ #define STIX_OBJ_FLAGS_TYPE_BITS 6 -#define STIX_OBJ_FLAGS_UNIT_BITS 4 +#define STIX_OBJ_FLAGS_UNIT_BITS 5 #define STIX_OBJ_FLAGS_EXTRA_BITS 1 #define STIX_OBJ_FLAGS_KERNEL_BITS 1 #define STIX_OBJ_FLAGS_MOVED_BITS 1