diff --git a/lib/dic.c b/lib/dic.c index 094242b..52b3237 100644 --- a/lib/dic.c +++ b/lib/dic.c @@ -81,7 +81,7 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) HCL_ASSERT (hcl, HCL_IS_CONS(hcl,ass)); key = (hcl_oop_char_t)ass->car; HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl,key)); - index = hcl_hashoochars(key->slot, HCL_OBJ_GET_SIZE(key)) % newsz; + index = hcl_hash_oochars(key->slot, HCL_OBJ_GET_SIZE(key)) % newsz; #else int n; HCL_ASSERT (hcl, HCL_IS_CONS(hcl,ass)); @@ -113,7 +113,7 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl,dic->bucket)); #if defined(SYMBOL_ONLY_KEY) - index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); + index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); #else if (hcl_hashobj(hcl, key, &index) <= -1) return HCL_NULL; index %= HCL_OBJ_GET_SIZE(dic->bucket); @@ -199,7 +199,7 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k #if defined(SYMBOL_ONLY_KEY) /* recalculate the index for the expanded bucket */ - index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); + index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); #else hcl_hashobj(hcl, key, &index); /* this must succeed as i know 'key' is hashable */ index %= HCL_OBJ_GET_SIZE(dic->bucket); @@ -286,7 +286,7 @@ int hcl_zapatdic (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t key) HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl,dic->bucket)); #if defined(SYMBOL_ONLY_KEY) - index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % bs; + index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % bs; #else if (hcl_hashobj(hcl, key, &index) <= -1) return -1; index %= bs; @@ -336,7 +336,7 @@ found: #if defined(SYMBOL_ONLY_KEY) /* get the natural hash index for the data in the slot at * the current hash index */ - z = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(ass->car), HCL_OBJ_GET_SIZE(ass->car)) % bs; + z = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(ass->car), HCL_OBJ_GET_SIZE(ass->car)) % bs; #else if (hcl_hashobj(hcl, ass->car, &z) <= -1) return -1; z %= bs; diff --git a/lib/gc.c b/lib/gc.c index 267ece8..36b9d2a 100644 --- a/lib/gc.c +++ b/lib/gc.c @@ -96,7 +96,7 @@ static void compact_symbol_table (hcl_t* hcl, hcl_oop_t _nil) HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, symbol)); - z = hcl_hashoochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % bucket_size; + z = hcl_hash_oochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % bucket_size; /* move an element if necessary */ if ((y > x && (z <= x || z > y)) || diff --git a/lib/hcl-cmn.h b/lib/hcl-cmn.h index 361bd9a..e321718 100644 --- a/lib/hcl-cmn.h +++ b/lib/hcl-cmn.h @@ -272,7 +272,7 @@ /* ========================================================================= * BASIC HCL TYPES - * =========================================================================*/ + * ========================================================================= */ typedef char hcl_bch_t; typedef int hcl_bci_t; @@ -348,6 +348,105 @@ typedef struct hcl_bcs_t hcl_bcs_t; /* the maximum number of bch charaters to represent a single uch character */ #define HCL_BCSIZE_MAX 6 +/* ========================================================================= + * BASIC OOP ENCODING + * ========================================================================= */ + +/* actual structure defined in hcl.h */ +typedef struct hcl_obj_t hcl_obj_t; +typedef struct hcl_obj_t* hcl_oop_t; + +/* + * An object pointer(OOP) is an ordinary pointer value to an object. + * but some simple numeric values are also encoded into OOP using a simple + * bit-shifting and masking. + * + * A real OOP is stored without any bit-shifting while a non-pointer value encoded + * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits + * are set to 1 or 2. + * + * This scheme works because the object allocators aligns the object size to + * a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits + * of a real OOP are always 0s. + * + * With 2 bits, i can encode only 3 special types except object pointers. + * Since I need more than 3 special types, I extend the tag bits up to 4 bits + * to represent a special data type that doesn't require a range as wide + * as a small integer. A unicode character, for instance, only requires 21 + * bits at most. An error doesn't need to be as diverse as a small integer. + */ + +#define HCL_OOP_TAG_BITS_LO 2 +#define HCL_OOP_TAG_BITS_HI 2 + +#define HCL_OOP_TAG_SMOOI 1 /* 01 */ +#define HCL_OOP_TAG_SMPTR 2 /* 10 */ +#define HCL_OOP_TAG_EXTENDED 3 /* 11 - internal use only */ +#define HCL_OOP_TAG_CHAR 3 /* 0011 */ +#define HCL_OOP_TAG_ERROR 7 /* 0111 */ +#define HCL_OOP_TAG_RESERVED0 11 /* 1011 */ +#define HCL_OOP_TAG_RESERVED1 15 /* 1111 */ + +#define HCL_OOP_GET_TAG_LO(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) +#define HCL_OOP_GET_TAG_LOHI(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) +#define HCL_OOP_GET_TAG(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_EXTENDED? HCL_OOP_GET_TAG_LOHI(oop): HCL_OOP_GET_TAG_LO(oop)) + +#define HCL_OOP_IS_NUMERIC(oop) (HCL_OOP_GET_TAG_LO(oop) != 0) +#define HCL_OOP_IS_POINTER(oop) (HCL_OOP_GET_TAG_LO(oop) == 0) + +#define HCL_OOP_IS_SMOOI(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMOOI) +#define HCL_OOP_IS_SMPTR(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMPTR) + +#define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMOOI)) +#define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) +/* +#define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)((((hcl_oow_t)(ptr)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMPTR)) +#define HCL_OOP_TO_SMPTR(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) +*/ +#define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)(((hcl_oow_t)ptr) | HCL_OOP_TAG_SMPTR)) +#define HCL_OOP_TO_SMPTR(oop) ((void*)(((hcl_oow_t)oop) & ~HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO))) + +#define HCL_OOP_IS_CHAR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_CHAR) +#define HCL_OOP_IS_ERROR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_ERROR) + +#define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) +#define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_CHAR)) +#define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) +#define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) + +/* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits + * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits + * respectively for the 1 sign bit. */ +#define HCL_SMOOI_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO) +#define HCL_SMOOI_ABS_BITS (HCL_SMOOI_BITS - 1) +#define HCL_SMOOI_MAX ((hcl_ooi_t)(~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + 1))) +/* Sacrificing 1 bit pattern for a negative SMOOI makes + * implementation a lot eaisier in many respect. */ +/*#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX - 1)*/ +#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) +#define HCL_IN_SMOOI_RANGE(ooi) ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) + + +/* SMPTR is a special value which has been devised to encode an address value + * whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer + * returned by most of system functions would be aligned to the pointer size. + * you can use the followings macros when converting such a pointer without loss. */ +#define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0) + +#define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) +#define HCL_CHAR_MIN 0 +#define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) + +#define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) +#define HCL_ERROR_MIN 0 +#define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) + +/* TODO: There are untested code where smint is converted to hcl_oow_t. + * for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. + * as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. + * later, please verify it works, probably by limiting the value ranges in such macros + */ + /* ========================================================================= * TIME-RELATED TYPES * =========================================================================*/ diff --git a/lib/hcl-utl.h b/lib/hcl-utl.h index d4d94b3..e0e88cd 100644 --- a/lib/hcl-utl.h +++ b/lib/hcl-utl.h @@ -116,46 +116,126 @@ #endif +#if (HCL_SIZEOF_SIZE_T == 4) +# define HCL_HASH_FNV_MAGIC_INIT (0x811c9dc5) +# define HCL_HASH_FNV_MAGIC_PRIME (0x01000193) +#elif (HCL_SIZEOF_SIZE_T == 8) + +# define HCL_HASH_FNV_MAGIC_INIT (0xCBF29CE484222325) +# define HCL_HASH_FNV_MAGIC_PRIME (0x100000001B3l) + +#elif (HCL_SIZEOF_SIZE_T == 16) +# define HCL_HASH_FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) +# define HCL_HASH_FNV_MAGIC_PRIME (0x1000000000000000000013B) +#endif + +#if defined(HCL_HASH_FNV_MAGIC_INIT) + /* FNV-1 hash */ +# define HCL_HASH_INIT HCL_HASH_FNV_MAGIC_INIT +# define HCL_HASH_VALUE(hv,v) (((hv) ^ (v)) * HCL_HASH_FNV_MAGIC_PRIME) + +#else + /* SDBM hash */ +# define HCL_HASH_INIT 0 +# define HCL_HASH_VALUE(hv,v) (((hv) << 6) + ((hv) << 16) - (hv) + (v)) +#endif + +#define HCL_HASH_VPTL(hv, ptr, len, type) do { \ + hv = HCL_HASH_INIT; \ + HCL_HASH_MORE_VPTL (hv, ptr, len, type); \ +} while(0) + +#define HCL_HASH_MORE_VPTL(hv, ptr, len, type) do { \ + type* __hcl_hash_more_vptl_p = (type*)(ptr); \ + type* __hcl_hash_more_vptl_q = (type*)__hcl_hash_more_vptl_p + (len); \ + while (__hcl_hash_more_vptl_p < __hcl_hash_more_vptl_q) \ + { \ + hv = HCL_HASH_VALUE(hv, *__hcl_hash_more_vptl_p); \ + __hcl_hash_more_vptl_p++; \ + } \ +} while(0) + +#define HCL_HASH_VPTR(hv, ptr, type) do { \ + hv = HCL_HASH_INIT; \ + HCL_HASH_MORE_VPTR (hv, ptr, type); \ +} while(0) + +#define HCL_HASH_MORE_VPTR(hv, ptr, type) do { \ + type* __hcl_hash_more_vptr_p = (type*)(ptr); \ + while (*__hcl_hash_more_vptr_p) \ + { \ + hv = HCL_HASH_VALUE(hv, *__hcl_hash_more_vptr_p); \ + __hcl_hash_more_vptr_p++; \ + } \ +} while(0) + +#define HCL_HASH_BYTES(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_uint8_t) +#define HCL_HASH_MORE_BYTES(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_uint8_t) + +#define HCL_HASH_BCHARS(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_bch_t) +#define HCL_HASH_MORE_BCHARS(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_bch_t) + +#define HCL_HASH_UCHARS(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_uch_t) +#define HCL_HASH_MORE_UCHARS(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_uch_t) + +#define HCL_HASH_BCSTR(hv, ptr) HCL_HASH_VPTR(hv, ptr, const hcl_bch_t) +#define HCL_HASH_MORE_BCSTR(hv, ptr) HCL_HASH_MORE_VPTR(hv, ptr, const hcl_bch_t) + +#define HCL_HASH_UCSTR(hv, ptr) HCL_HASH_VPTR(hv, ptr, const hcl_uch_t) +#define HCL_HASH_MORE_UCSTR(hv, ptr) HCL_HASH_MORE_VPTR(hv, ptr, const hcl_uch_t) + + + #if defined(__cplusplus) extern "C" { #endif -HCL_EXPORT hcl_oow_t hcl_hash_bytes ( +HCL_EXPORT hcl_oow_t hcl_hash_bytes_ ( const hcl_oob_t* ptr, hcl_oow_t len ); #if defined(HCL_HAVE_INLINE) - static HCL_INLINE hcl_oow_t hcl_hashbchars (const hcl_bch_t* ptr, hcl_oow_t len) + static HCL_INLINE hcl_oow_t hcl_hash_bytes (const hcl_oob_t* ptr, hcl_oow_t len) + { + hcl_oow_t hv; + HCL_HASH_BYTES (hv, ptr, len); + /* constrain the hash value to be representable in a small integer + * for convenience sake */ + return hv % ((hcl_oow_t)HCL_SMOOI_MAX + 1); + } + + static HCL_INLINE hcl_oow_t hcl_hash_bchars (const hcl_bch_t* ptr, hcl_oow_t len) { return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)); } - static HCL_INLINE hcl_oow_t hcl_hashuchars (const hcl_uch_t* ptr, hcl_oow_t len) + static HCL_INLINE hcl_oow_t hcl_hash_uchars (const hcl_uch_t* ptr, hcl_oow_t len) { return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)); } - static HCL_INLINE hcl_oow_t hcl_hashwords (const hcl_oow_t* ptr, hcl_oow_t len) + static HCL_INLINE hcl_oow_t hcl_hash_words (const hcl_oow_t* ptr, hcl_oow_t len) { return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)); } - static HCL_INLINE hcl_oow_t hcl_hashhalfwords (const hcl_oohw_t* ptr, hcl_oow_t len) + static HCL_INLINE hcl_oow_t hcl_hash_halfwords (const hcl_oohw_t* ptr, hcl_oow_t len) { return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)); } #else -# define hcl_hashbchars(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)) -# define hcl_hashuchars(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)) -# define hcl_hashwords(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)) -# define hcl_hashhalfwords(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)) +# define hcl_hash_bytes(ptr,len) hcl_hash_bytes_(ptr, len) +# define hcl_hash_bchars(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)) +# define hcl_hash_uchars(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)) +# define hcl_hash_words(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)) +# define hcl_hash_halfwords(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)) #endif #if defined(HCL_OOCH_IS_UCH) -# define hcl_hashoochars(ptr,len) hcl_hashuchars(ptr,len) +# define hcl_hash_oochars(ptr,len) hcl_hash_uchars(ptr,len) #else -# define hcl_hashoochars(ptr,len) hcl_hashbchars(ptr,len) +# define hcl_hash_oochars(ptr,len) hcl_hash_bchars(ptr,len) #endif /** diff --git a/lib/hcl.h b/lib/hcl.h index e138a3a..6d7cbff 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -196,8 +196,12 @@ enum hcl_trait_t }; typedef enum hcl_trait_t hcl_trait_t; -typedef struct hcl_obj_t hcl_obj_t; -typedef struct hcl_obj_t* hcl_oop_t; +/* ========================================================================= + * SPECIALIZED OOP TYPES + * ========================================================================= */ + +/* hcl_oop_t defined in hcl-cmn.h + * hcl_obj_t defined further down */ /* these are more specialized types for hcl_obj_t */ typedef struct hcl_obj_oop_t hcl_obj_oop_t; @@ -219,9 +223,9 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t; #define HCL_OOHW_BITS (HCL_SIZEOF_OOHW_T * 8) -/* ========================================================================= */ -/* BIGINT TYPES AND MACROS */ -/* ========================================================================= */ +/* ========================================================================= + * BIGINT TYPES AND MACROS + * ========================================================================= */ #if (HCL_SIZEOF_UINTMAX_T > HCL_SIZEOF_OOW_T) # define HCL_USE_FULL_WORD #endif @@ -254,102 +258,9 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t; #endif - -/* - * OOP encoding - * An object pointer(OOP) is an ordinary pointer value to an object. - * but some simple numeric values are also encoded into OOP using a simple - * bit-shifting and masking. - * - * A real OOP is stored without any bit-shifting while a non-pointer value encoded - * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits - * are set to 1 or 2. - * - * This scheme works because the object allocators aligns the object size to - * a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits - * of a real OOP are always 0s. - * - * With 2 bits, i can encode only 3 special types except object pointers. - * Since I need more than 3 special types, I extend the tag bits up to 4 bits - * to represent a special data type that doesn't require a range as wide - * as a small integer. A unicode character, for instance, only requires 21 - * bits at most. An error doesn't need to be as diverse as a small integer. - */ - -#define HCL_OOP_TAG_BITS_LO 2 -#define HCL_OOP_TAG_BITS_HI 2 - -#define HCL_OOP_TAG_SMOOI 1 /* 01 */ -#define HCL_OOP_TAG_SMPTR 2 /* 10 */ -#define HCL_OOP_TAG_EXTENDED 3 /* 11 - internal use only */ -#define HCL_OOP_TAG_CHAR 3 /* 0011 */ -#define HCL_OOP_TAG_ERROR 7 /* 0111 */ -#define HCL_OOP_TAG_RESERVED0 11 /* 1011 */ -#define HCL_OOP_TAG_RESERVED1 15 /* 1111 */ - -#define HCL_OOP_GET_TAG_LO(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) -#define HCL_OOP_GET_TAG_LOHI(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) -#define HCL_OOP_GET_TAG(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_EXTENDED? HCL_OOP_GET_TAG_LOHI(oop): HCL_OOP_GET_TAG_LO(oop)) - -#define HCL_OOP_IS_NUMERIC(oop) (HCL_OOP_GET_TAG_LO(oop) != 0) -#define HCL_OOP_IS_POINTER(oop) (HCL_OOP_GET_TAG_LO(oop) == 0) - -#define HCL_OOP_IS_SMOOI(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMOOI) -#define HCL_OOP_IS_SMPTR(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMPTR) - -#define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMOOI)) -#define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) -/* -#define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)((((hcl_oow_t)(ptr)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMPTR)) -#define HCL_OOP_TO_SMPTR(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) -*/ -#define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)(((hcl_oow_t)ptr) | HCL_OOP_TAG_SMPTR)) -#define HCL_OOP_TO_SMPTR(oop) ((void*)(((hcl_oow_t)oop) & ~HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO))) - -#define HCL_OOP_IS_CHAR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_CHAR) -#define HCL_OOP_IS_ERROR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_ERROR) - -#define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) -#define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_CHAR)) -#define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) -#define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) - -/* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits - * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits - * respectively for the 1 sign bit. */ -#define HCL_SMOOI_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO) -#define HCL_SMOOI_ABS_BITS (HCL_SMOOI_BITS - 1) -#define HCL_SMOOI_MAX ((hcl_ooi_t)(~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + 1))) -/* Sacrificing 1 bit pattern for a negative SMOOI makes - * implementation a lot eaisier in many respect. */ -/*#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX - 1)*/ -#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) -#define HCL_IN_SMOOI_RANGE(ooi) ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) - - -/* SMPTR is a special value which has been devised to encode an address value - * whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer - * returned by most of system functions would be aligned to the pointer size. - * you can use the followings macros when converting such a pointer without loss. */ -#define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0) - -#define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) -#define HCL_CHAR_MIN 0 -#define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) - -#define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) -#define HCL_ERROR_MIN 0 -#define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) - -/* TODO: There are untested code where smint is converted to hcl_oow_t. - * for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. - * as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. - * later, please verify it works, probably by limiting the value ranges in such macros - */ - -/* - * Object structure - */ +/* ========================================================================= + * OBJECT STRUCTURE + * ========================================================================= */ enum hcl_obj_type_t { HCL_OBJ_TYPE_OOP, @@ -706,6 +617,10 @@ struct hcl_process_scheduler_t #define HCL_ISTYPEOF(hcl,oop,type) \ (!HCL_OOP_IS_NUMERIC(oop) && HCL_OBJ_GET_FLAGS_TYPE(oop) == (type)) +/* ========================================================================= + * HEAP + * ========================================================================= */ + typedef struct hcl_heap_t hcl_heap_t; struct hcl_heap_t @@ -716,7 +631,7 @@ struct hcl_heap_t }; /* ========================================================================= - * HCL VM LOGGING + * VM LOGGING * ========================================================================= */ enum hcl_log_mask_t diff --git a/lib/obj.c b/lib/obj.c index 2441e44..f69abc6 100644 --- a/lib/obj.c +++ b/lib/obj.c @@ -477,15 +477,15 @@ int hcl_hashobj (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* xhv) break; case HCL_OBJ_TYPE_CHAR: - hv = hcl_hashoochars (((hcl_oop_char_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); + hv = hcl_hash_oochars (((hcl_oop_char_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); break; case HCL_OBJ_TYPE_HALFWORD: - hv = hcl_hashhalfwords(((hcl_oop_halfword_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); + hv = hcl_hash_halfwords(((hcl_oop_halfword_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); break; case HCL_OBJ_TYPE_WORD: - hv = hcl_hashwords(((hcl_oop_word_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); + hv = hcl_hash_words(((hcl_oop_word_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); break; default: diff --git a/lib/sym.c b/lib/sym.c index d69c8dc..08a57ad 100644 --- a/lib/sym.c +++ b/lib/sym.c @@ -73,7 +73,7 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, symbol)); /*HCL_ASSERT (hcl, sym->size > 0);*/ - index = hcl_hashoochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % newsz; + index = hcl_hash_oochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % newsz; while (newbuc->slot[index] != hcl->_nil) index = (index + 1) % newsz; newbuc->slot[index] = (hcl_oop_t)symbol; } @@ -97,7 +97,7 @@ static hcl_oop_t find_or_make_symbol (hcl_t* hcl, const hcl_ooch_t* ptr, hcl_oow } HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl, hcl->symtab->bucket)); - index = hcl_hashoochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); + index = hcl_hash_oochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); /* find a matching symbol in the open-addressed symbol table */ while (hcl->symtab->bucket->slot[index] != hcl->_nil) @@ -153,7 +153,7 @@ static hcl_oop_t find_or_make_symbol (hcl_t* hcl, const hcl_ooch_t* ptr, hcl_oow hcl->symtab->bucket = bucket; /* recalculate the index for the expanded bucket */ - index = hcl_hashoochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); + index = hcl_hash_oochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); while (hcl->symtab->bucket->slot[index] != hcl->_nil) index = (index + 1) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); diff --git a/lib/utl.c b/lib/utl.c index 3eaf89e..de0c747 100644 --- a/lib/utl.c +++ b/lib/utl.c @@ -35,48 +35,13 @@ * utobcstr -> ucstr to bcstr */ -#if HCL_SIZEOF_OOW_T == 4 -# define FNV_MAGIC_INIT (0x811c9dc5) -# define FNV_MAGIC_PRIME (0x01000193) -#elif HCL_SIZEOF_OOW_T == 8 -# define FNV_MAGIC_INIT (0xCBF29CE484222325) -# define FNV_MAGIC_PRIME (0x100000001B3) -#elif HCL_SIZEOF_OOW_T == 16 -# define FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) -# define FNV_MAGIC_PRIME (0x1000000000000000000013B) -#endif - -hcl_oow_t hcl_hash_bytes (const hcl_oob_t* ptr, hcl_oow_t len) +hcl_oow_t hcl_hash_bytes_ (const hcl_oob_t* ptr, hcl_oow_t len) { - hcl_oow_t h; - const hcl_uint8_t* bp, * be; - - bp = ptr; be = bp + len; - - /* this hash doesn't produce good distribution */ - /* - h = 0 - while (bp < be) h = h * 31 + *bp++; - */ - -#if defined(FNV_MAGIC_INIT) - /* FNV-1 hash */ - h = FNV_MAGIC_INIT; - while (bp < be) - { - h ^= (hcl_oow_t)(*bp++); - h *= FNV_MAGIC_PRIME; - } -#else - /* SDBM hash is known to produce good overall distribution - * for many different data sets */ - h = 0; - while (bp < be) h = (h << 6) + (h << 16) - h + *bp++; -#endif - + hcl_oow_t hv; + HCL_HASH_BYTES (hv, ptr, len); /* constrain the hash value to be representable in a small integer * for convenience sake */ - return h % ((hcl_oow_t)HCL_SMOOI_MAX + 1); + return hv % ((hcl_oow_t)HCL_SMOOI_MAX + 1); } int hcl_equal_uchars (const hcl_uch_t* str1, const hcl_uch_t* str2, hcl_oow_t len)