diff --git a/moo/lib/dic.c b/moo/lib/dic.c index 0ee6353..c453e1b 100644 --- a/moo/lib/dic.c +++ b/moo/lib/dic.c @@ -77,7 +77,7 @@ static moo_oop_oop_t expand_bucket (moo_t* moo, moo_oop_oop_t oldbuc) key = (moo_oop_char_t)ass->key; MOO_ASSERT (moo, MOO_CLASSOF(moo,key) == moo->_symbol); - index = moo_hashoochars(MOO_OBJ_GET_CHAR_SLOT(key), MOO_OBJ_GET_SIZE(key)) % newsz; + index = moo_hash_oochars(MOO_OBJ_GET_CHAR_SLOT(key), MOO_OBJ_GET_SIZE(key)) % newsz; while (MOO_OBJ_GET_OOP_VAL(newbuc, index) != moo->_nil) index = (index + 1) % newsz; MOO_STORE_OOP (moo, MOO_OBJ_GET_OOP_PTR(newbuc, index), (moo_oop_t)ass); @@ -101,7 +101,7 @@ static moo_oop_association_t find_or_upsert (moo_t* moo, moo_oop_dic_t dic, moo_ MOO_ASSERT (moo, MOO_CLASSOF(moo,dic->tally) == moo->_small_integer); MOO_ASSERT (moo, MOO_CLASSOF(moo,dic->bucket) == moo->_array); - hv = moo_hashoochars(MOO_OBJ_GET_CHAR_SLOT(key), MOO_OBJ_GET_SIZE(key)); + hv = moo_hash_oochars(MOO_OBJ_GET_CHAR_SLOT(key), MOO_OBJ_GET_SIZE(key)); index = hv % MOO_OBJ_GET_SIZE(dic->bucket); /* find */ @@ -207,7 +207,7 @@ moo_oop_association_t moo_lookupdic_noseterr (moo_t* moo, moo_oop_dic_t dic, con MOO_ASSERT (moo, MOO_CLASSOF(moo,dic->tally) == moo->_small_integer); MOO_ASSERT (moo, MOO_CLASSOF(moo,dic->bucket) == moo->_array); - index = moo_hashoochars(name->ptr, name->len) % MOO_OBJ_GET_SIZE(dic->bucket); + index = moo_hash_oochars(name->ptr, name->len) % MOO_OBJ_GET_SIZE(dic->bucket); while ((moo_oop_t)(ass = (moo_oop_association_t)MOO_OBJ_GET_OOP_VAL(dic->bucket, index)) != moo->_nil) { @@ -289,7 +289,7 @@ int moo_deletedic (moo_t* moo, moo_oop_dic_t dic, const moo_oocs_t* name) tally = MOO_OOP_TO_SMOOI(dic->tally); bs = MOO_OBJ_GET_SIZE(dic->bucket); - hv = moo_hashoochars(name->ptr, name->len) % bs; + hv = moo_hash_oochars(name->ptr, name->len) % bs; index = hv % bs; /* find */ @@ -322,7 +322,7 @@ found: /* otherwise get the natural hash index for the data in the slot at * the current hash index */ - z = moo_hashoochars(MOO_OBJ_GET_CHAR_SLOT(ass->key), MOO_OBJ_GET_SIZE(ass->key)) % bs; + z = moo_hash_oochars(MOO_OBJ_GET_CHAR_SLOT(ass->key), MOO_OBJ_GET_SIZE(ass->key)) % bs; /* move an element if necesary */ if ((y > x && (z <= x || z > y)) || (y < x && (z <= x && z > y))) diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 3036d11..3401a0f 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2003,15 +2003,15 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) break; case MOO_OBJ_TYPE_CHAR: - hv = moo_hashoochars (MOO_OBJ_GET_CHAR_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); + hv = moo_hash_oochars (MOO_OBJ_GET_CHAR_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); break; case MOO_OBJ_TYPE_HALFWORD: - hv = moo_hashhalfwords(MOO_OBJ_GET_HALFWORD_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); + hv = moo_hash_halfwords(MOO_OBJ_GET_HALFWORD_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); break; case MOO_OBJ_TYPE_WORD: - hv = moo_hashwords(MOO_OBJ_GET_WORD_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); + hv = moo_hash_words(MOO_OBJ_GET_WORD_SLOT(rcv), MOO_OBJ_GET_SIZE(rcv)); break; default: diff --git a/moo/lib/fmtoutv.h b/moo/lib/fmtoutv.h index b676dee..f34dfbc 100644 --- a/moo/lib/fmtoutv.h +++ b/moo/lib/fmtoutv.h @@ -460,8 +460,8 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v #endif lowercase_s: - bsp = va_arg (ap, moo_bch_t*); - if (bsp == MOO_NULL) bsp = bch_nullstr; + bsp = va_arg(ap, moo_bch_t*); + if (!bsp) bsp = bch_nullstr; #if defined(MOO_OOCH_IS_UCH) /* get the length */ @@ -536,8 +536,8 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v if (lm_flag & LF_J) goto lowercase_s; #endif uppercase_s: - usp = va_arg (ap, moo_uch_t*); - if (usp == MOO_NULL) usp = uch_nullstr; + usp = va_arg(ap, moo_uch_t*); + if (!usp) usp = uch_nullstr; #if defined(MOO_OOCH_IS_BCH) /* get the length */ @@ -682,15 +682,15 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v { if (fltfmt->ptr == fltfmt->buf) { - fltfmt->ptr = MOO_MMGR_ALLOC (MOO_MMGR_GETDFL(), MOO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); - if (fltfmt->ptr == MOO_NULL) goto oops; + fltfmt->ptr = MOO_MMGR_ALLOC(MOO_MMGR_GETDFL(), MOO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); + if (!fltfmt->ptr) goto oops; } else { - moo_mchar_t* tmpptr; + moo_bch_t* tmpptr; - tmpptr = MOO_MMGR_REALLOC (MOO_MMGR_GETDFL(), fltfmt->ptr, MOO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); - if (tmpptr == MOO_NULL) goto oops; + tmpptr = MOO_MMGR_REALLOC(MOO_MMGR_GETDFL(), fltfmt->ptr, MOO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); + if (!tmpptr) goto oops; fltfmt->ptr = tmpptr; } @@ -742,8 +742,8 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v { MOO_ASSERT (moo, fltout->ptr == fltout->buf); - fltout->ptr = MOO_MMGR_ALLOC (MOO_MMGR_GETDFL(), MOO_SIZEOF(char_t) * (newcapa + 1)); - if (fltout->ptr == MOO_NULL) goto oops; + fltout->ptr = MOO_MMGR_ALLOC(MOO_MMGR_GETDFL(), MOO_SIZEOF(char_t) * (newcapa + 1)); + if (!fltout->ptr) goto oops; fltout->capa = newcapa; } #endif @@ -754,23 +754,23 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v if (dtype == LF_LD) { #if defined(HAVE_SNPRINTF) - q = snprintf ((moo_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_ld); + q = snprintf ((moo_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_ld); #else - q = sprintf ((moo_mchar_t*)fltout->ptr, fltfmt->ptr, v_ld); + q = sprintf ((moo_bch_t*)fltout->ptr, fltfmt->ptr, v_ld); #endif } #if (MOO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) else if (dtype == LF_QD) { - q = quadmath_snprintf ((moo_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_qd); + q = quadmath_snprintf((moo_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_qd); } #endif else { #if defined(HAVE_SNPRINTF) - q = snprintf ((moo_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_d); + q = snprintf ((moo_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_d); #else - q = sprintf ((moo_mchar_t*)fltout->ptr, fltfmt->ptr, v_d); + q = sprintf ((moo_bch_t*)fltout->ptr, fltfmt->ptr, v_d); #endif } if (q <= -1) goto oops; @@ -781,27 +781,27 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v if (fltout->ptr == fltout->sbuf) { - fltout->ptr = MOO_MMGR_ALLOC (MOO_MMGR_GETDFL(), MOO_SIZEOF(char_t) * (newcapa + 1)); - if (fltout->ptr == MOO_NULL) goto oops; + fltout->ptr = MOO_MMGR_ALLOC(MOO_MMGR_GETDFL(), MOO_SIZEOF(char_t) * (newcapa + 1)); + if (!fltout->ptr) goto oops; } else { char_t* tmpptr; - tmpptr = MOO_MMGR_REALLOC (MOO_MMGR_GETDFL(), fltout->ptr, MOO_SIZEOF(char_t) * (newcapa + 1)); - if (tmpptr == MOO_NULL) goto oops; + tmpptr = MOO_MMGR_REALLOC(MOO_MMGR_GETDFL(), fltout->ptr, MOO_SIZEOF(char_t) * (newcapa + 1)); + if (!tmpptr) goto oops; fltout->ptr = tmpptr; } fltout->capa = newcapa; } - if (MOO_SIZEOF(char_t) != MOO_SIZEOF(moo_mchar_t)) + if (MOO_SIZEOF(char_t) != MOO_SIZEOF(moo_bch_t)) { fltout->ptr[q] = '\0'; while (q > 0) { q--; - fltout->ptr[q] = ((moo_mchar_t*)fltout->ptr)[q]; + fltout->ptr[q] = ((moo_bch_t*)fltout->ptr)[q]; } } diff --git a/moo/lib/gc.c b/moo/lib/gc.c index a698c37..f68a7d9 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -682,7 +682,7 @@ static void compact_symbol_table (moo_t* moo, moo_oop_t _nil) /* get the natural hash index for the data in the slot * at the current hash index */ MOO_ASSERT (moo, MOO_CLASSOF(moo,tmp) == moo->_symbol); - z = moo_hashoochars(MOO_OBJ_GET_CHAR_SLOT(tmp), MOO_OBJ_GET_SIZE(tmp)) % bucket_size; + z = moo_hash_oochars(MOO_OBJ_GET_CHAR_SLOT(tmp), MOO_OBJ_GET_SIZE(tmp)) % bucket_size; /* move an element if necessary */ if ((y > x && (z <= x || z > y)) || (y < x && (z <= x && z > y))) diff --git a/moo/lib/moo-cmn.h b/moo/lib/moo-cmn.h index a111d2a..46a8a66 100644 --- a/moo/lib/moo-cmn.h +++ b/moo/lib/moo-cmn.h @@ -271,7 +271,7 @@ /* ========================================================================= * BASIC MOO TYPES - * =========================================================================*/ + * ========================================================================= */ typedef char moo_bch_t; typedef int moo_bci_t; @@ -347,6 +347,108 @@ typedef struct moo_bcs_t moo_bcs_t; /* the maximum number of bch charaters to represent a single uch character */ #define MOO_BCSIZE_MAX 6 + +/* ========================================================================= + * BASIC OOP ENCODING + * ========================================================================= */ + +/* actual structure defined in moo.h */ +typedef struct moo_obj_t moo_obj_t; +typedef struct moo_obj_t* moo_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(moo_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 MOO_OOP_TAG_BITS_LO 2 +#define MOO_OOP_TAG_BITS_HI 2 + +#define MOO_OOP_TAG_SMOOI 1 /* 01 */ +#define MOO_OOP_TAG_SMPTR 2 /* 10 */ +#define MOO_OOP_TAG_EXTENDED 3 /* 11 - internal use only */ +#define MOO_OOP_TAG_CHAR 3 /* 0011 */ +#define MOO_OOP_TAG_ERROR 7 /* 0111 */ +#define MOO_OOP_TAG_RESERVED0 11 /* 1011 */ +#define MOO_OOP_TAG_RESERVED1 15 /* 1111 */ + +#define MOO_OOP_GET_TAG_LO(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) +#define MOO_OOP_GET_TAG_LOHI(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) +#define MOO_OOP_GET_TAG(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_EXTENDED? MOO_OOP_GET_TAG_LOHI(oop): MOO_OOP_GET_TAG_LO(oop)) + +#define MOO_OOP_IS_NUMERIC(oop) (MOO_OOP_GET_TAG_LO(oop) != 0) +#define MOO_OOP_IS_POINTER(oop) (MOO_OOP_GET_TAG_LO(oop) == 0) + +#define MOO_OOP_IS_SMOOI(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMOOI) +#define MOO_OOP_IS_SMPTR(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMPTR) + +#define MOO_SMOOI_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMOOI)) +#define MOO_OOP_TO_SMOOI(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO) +/* +#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)((((moo_oow_t)(ptr)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMPTR)) +#define MOO_OOP_TO_SMPTR(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO) +*/ +#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)(((moo_oow_t)ptr) | MOO_OOP_TAG_SMPTR)) +#define MOO_OOP_TO_SMPTR(oop) ((void*)(((moo_oow_t)oop) & ~MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO))) + +#define MOO_OOP_IS_CHAR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_CHAR) +#define MOO_OOP_IS_ERROR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_ERROR) + +#define MOO_OOP_TO_CHAR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) +#define MOO_CHAR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_CHAR)) +#define MOO_OOP_TO_ERROR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) +#define MOO_ERROR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_ERROR)) + +/* -------------------------------- */ + +/* SMOOI takes up 62 bits 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 sign bit. */ +#define MOO_SMOOI_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO) +#define MOO_SMOOI_ABS_BITS (MOO_SMOOI_BITS - 1) +#define MOO_SMOOI_MAX ((moo_ooi_t)(~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + 1))) +/* Sacrificing 1 bit pattern for a negative SMOOI makes + * implementation a lot eaisier in many aspects. */ +/*#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX - 1)*/ +#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX) +#define MOO_IN_SMOOI_RANGE(ooi) ((ooi) >= MOO_SMOOI_MIN && (ooi) <= MOO_SMOOI_MAX) + +/* SMPTR is a special value which has been devised to encode an address value + * whose low MOO_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 MOO_IN_SMPTR_RANGE(ptr) ((((moo_oow_t)ptr) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) == 0) + +#define MOO_CHAR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI) +#define MOO_CHAR_MIN 0 +#define MOO_CHAR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) + +#define MOO_ERROR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI) +#define MOO_ERROR_MIN 0 +#define MOO_ERROR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) + +/* TODO: There are untested code where a small integer is converted to moo_oow_t. + * for example, the spec making macro treats the number as moo_oow_t instead of moo_ooi_t. + * as of this writing, i skip testing that part with the spec value exceeding MOO_SMOOI_MAX. + * later, please verify it works, probably by limiting the value ranges in such macros + */ + + /* ========================================================================= * TIME-RELATED TYPES * =========================================================================*/ diff --git a/moo/lib/moo-utl.h b/moo/lib/moo-utl.h index 9ca548c..25130c7 100644 --- a/moo/lib/moo-utl.h +++ b/moo/lib/moo-utl.h @@ -29,10 +29,9 @@ #include "moo-cmn.h" - -/* ----------------------------------------------------------------------- - * DOUBLY LINKED LIST MACROS - * ----------------------------------------------------------------------- */ +/* ========================================================================= + * DOUBLY LINKED LIST + * ========================================================================= */ #define MOO_APPEND_TO_LIST(list, node) do { \ (node)->next = MOO_NULL; \ (node)->prev = (list)->last; \ @@ -57,7 +56,6 @@ } while(0) - #define MOO_APPEND_TO_OOP_LIST(moo, list, node_type, node, _link) do { \ (node)->_link.next = (node_type)(moo)->_nil; \ (node)->_link.prev = (list)->last; \ @@ -89,8 +87,9 @@ } while(0); */ - - +/* ========================================================================= + * ENDIAN CHANGE + * ========================================================================= */ #define MOO_CONST_SWAP16(x) \ ((qse_uint16_t)((((qse_uint16_t)(x) & (qse_uint16_t)0x00ffU) << 8) | \ (((qse_uint16_t)(x) & (qse_uint16_t)0xff00U) >> 8) )) @@ -116,46 +115,129 @@ #endif +/* ========================================================================= + * HASH + * ========================================================================= */ + +#if (MOO_SIZEOF_SIZE_T == 4) +# define MOO_HASH_FNV_MAGIC_INIT (0x811c9dc5) +# define MOO_HASH_FNV_MAGIC_PRIME (0x01000193) +#elif (MOO_SIZEOF_SIZE_T == 8) + +# define MOO_HASH_FNV_MAGIC_INIT (0xCBF29CE484222325) +# define MOO_HASH_FNV_MAGIC_PRIME (0x100000001B3l) + +#elif (MOO_SIZEOF_SIZE_T == 16) +# define MOO_HASH_FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) +# define MOO_HASH_FNV_MAGIC_PRIME (0x1000000000000000000013B) +#endif + +#if defined(MOO_HASH_FNV_MAGIC_INIT) + /* FNV-1 hash */ +# define MOO_HASH_INIT MOO_HASH_FNV_MAGIC_INIT +# define MOO_HASH_VALUE(hv,v) (((hv) ^ (v)) * MOO_HASH_FNV_MAGIC_PRIME) + +#else + /* SDBM hash */ +# define MOO_HASH_INIT 0 +# define MOO_HASH_VALUE(hv,v) (((hv) << 6) + ((hv) << 16) - (hv) + (v)) +#endif + +#define MOO_HASH_VPTL(hv, ptr, len, type) do { \ + hv = MOO_HASH_INIT; \ + MOO_HASH_MORE_VPTL (hv, ptr, len, type); \ +} while(0) + +#define MOO_HASH_MORE_VPTL(hv, ptr, len, type) do { \ + type* __moo_hash_more_vptl_p = (type*)(ptr); \ + type* __moo_hash_more_vptl_q = (type*)__moo_hash_more_vptl_p + (len); \ + while (__moo_hash_more_vptl_p < __moo_hash_more_vptl_q) \ + { \ + hv = MOO_HASH_VALUE(hv, *__moo_hash_more_vptl_p); \ + __moo_hash_more_vptl_p++; \ + } \ +} while(0) + +#define MOO_HASH_VPTR(hv, ptr, type) do { \ + hv = MOO_HASH_INIT; \ + MOO_HASH_MORE_VPTR (hv, ptr, type); \ +} while(0) + +#define MOO_HASH_MORE_VPTR(hv, ptr, type) do { \ + type* __moo_hash_more_vptr_p = (type*)(ptr); \ + while (*__moo_hash_more_vptr_p) \ + { \ + hv = MOO_HASH_VALUE(hv, *__moo_hash_more_vptr_p); \ + __moo_hash_more_vptr_p++; \ + } \ +} while(0) + +#define MOO_HASH_BYTES(hv, ptr, len) MOO_HASH_VPTL(hv, ptr, len, const moo_uint8_t) +#define MOO_HASH_MORE_BYTES(hv, ptr, len) MOO_HASH_MORE_VPTL(hv, ptr, len, const moo_uint8_t) + +#define MOO_HASH_BCHARS(hv, ptr, len) MOO_HASH_VPTL(hv, ptr, len, const moo_bch_t) +#define MOO_HASH_MORE_BCHARS(hv, ptr, len) MOO_HASH_MORE_VPTL(hv, ptr, len, const moo_bch_t) + +#define MOO_HASH_UCHARS(hv, ptr, len) MOO_HASH_VPTL(hv, ptr, len, const moo_uch_t) +#define MOO_HASH_MORE_UCHARS(hv, ptr, len) MOO_HASH_MORE_VPTL(hv, ptr, len, const moo_uch_t) + +#define MOO_HASH_BCSTR(hv, ptr) MOO_HASH_VPTR(hv, ptr, const moo_bch_t) +#define MOO_HASH_MORE_BCSTR(hv, ptr) MOO_HASH_MORE_VPTR(hv, ptr, const moo_bch_t) + +#define MOO_HASH_UCSTR(hv, ptr) MOO_HASH_VPTR(hv, ptr, const moo_uch_t) +#define MOO_HASH_MORE_UCSTR(hv, ptr) MOO_HASH_MORE_VPTR(hv, ptr, const moo_uch_t) + + #if defined(__cplusplus) extern "C" { #endif -MOO_EXPORT moo_oow_t moo_hash_bytes ( +MOO_EXPORT moo_oow_t moo_hash_bytes_ ( const moo_oob_t* ptr, moo_oow_t len ); #if defined(MOO_HAVE_INLINE) - static MOO_INLINE moo_oow_t moo_hashbchars (const moo_bch_t* ptr, moo_oow_t len) + static MOO_INLINE moo_oow_t moo_hash_bytes (const moo_oob_t* ptr, moo_oow_t len) + { + moo_oow_t hv; + MOO_HASH_BYTES (hv, ptr, len); + /* constrain the hash value to be representable in a small integer + * for convenience sake */ + return hv % ((moo_oow_t)MOO_SMOOI_MAX + 1); + } + + static MOO_INLINE moo_oow_t moo_hash_bchars (const moo_bch_t* ptr, moo_oow_t len) { return moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_bch_t)); } - static MOO_INLINE moo_oow_t moo_hashuchars (const moo_uch_t* ptr, moo_oow_t len) + static MOO_INLINE moo_oow_t moo_hash_uchars (const moo_uch_t* ptr, moo_oow_t len) { return moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_uch_t)); } - static MOO_INLINE moo_oow_t moo_hashwords (const moo_oow_t* ptr, moo_oow_t len) + static MOO_INLINE moo_oow_t moo_hash_words (const moo_oow_t* ptr, moo_oow_t len) { return moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_oow_t)); } - static MOO_INLINE moo_oow_t moo_hashhalfwords (const moo_oohw_t* ptr, moo_oow_t len) + static MOO_INLINE moo_oow_t moo_hash_halfwords (const moo_oohw_t* ptr, moo_oow_t len) { return moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_oohw_t)); } #else -# define moo_hashbchars(ptr,len) moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_bch_t)) -# define moo_hashuchars(ptr,len) moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_uch_t)) -# define moo_hashwords(ptr,len) moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_oow_t)) -# define moo_hashhalfwords(ptr,len) moo_hash_bytes((const moo_oob_t*)ptr, len * MOO_SIZEOF(moo_oohw_t)) +# define moo_hash_bytes(ptr,len) moo_hash_bytes_(ptr, len) +# define moo_hash_bchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_bch_t)) +# define moo_hash_uchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_uch_t)) +# define moo_hash_words(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oow_t)) +# define moo_hash_halfwords(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oohw_t)) #endif #if defined(MOO_OOCH_IS_UCH) -# define moo_hashoochars(ptr,len) moo_hashuchars(ptr,len) +# define moo_hash_oochars(ptr,len) moo_hash_uchars(ptr,len) #else -# define moo_hashoochars(ptr,len) moo_hashbchars(ptr,len) +# define moo_hash_oochars(ptr,len) moo_hash_bchars(ptr,len) #endif /** diff --git a/moo/lib/moo.h b/moo/lib/moo.h index c5e2a1e..85f08fa 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -131,8 +131,13 @@ enum moo_trait_t }; typedef enum moo_trait_t moo_trait_t; -typedef struct moo_obj_t moo_obj_t; -typedef struct moo_obj_t* moo_oop_t; + +/* ========================================================================= + * SPECIALIZED OOP TYPES + * ========================================================================= */ + +/* moo_oop_t defined in moo-cmn.h + * moo_obj_t defined further down */ /* these are more specialized types for moo_obj_t */ typedef struct moo_obj_oop_t moo_obj_oop_t; @@ -154,9 +159,9 @@ typedef struct moo_obj_word_t* moo_oop_word_t; #define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * 8) -/* ========================================================================= */ -/* BIGINT TYPES AND MACROS */ -/* ========================================================================= */ +/* ========================================================================= + * BIGINT TYPES AND MACROS + * ========================================================================= */ #if (MOO_SIZEOF_UINTMAX_T > MOO_SIZEOF_OOW_T) # define MOO_USE_FULL_WORD #endif @@ -197,102 +202,9 @@ enum moo_method_type_t }; typedef enum moo_method_type_t moo_method_type_t; -/* - * 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(moo_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 MOO_OOP_TAG_BITS_LO 2 -#define MOO_OOP_TAG_BITS_HI 2 - -#define MOO_OOP_TAG_SMOOI 1 /* 01 */ -#define MOO_OOP_TAG_SMPTR 2 /* 10 */ -#define MOO_OOP_TAG_EXTENDED 3 /* 11 - internal use only */ -#define MOO_OOP_TAG_CHAR 3 /* 0011 */ -#define MOO_OOP_TAG_ERROR 7 /* 0111 */ -#define MOO_OOP_TAG_RESERVED0 11 /* 1011 */ -#define MOO_OOP_TAG_RESERVED1 15 /* 1111 */ - -#define MOO_OOP_GET_TAG_LO(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) -#define MOO_OOP_GET_TAG_LOHI(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) -#define MOO_OOP_GET_TAG(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_EXTENDED? MOO_OOP_GET_TAG_LOHI(oop): MOO_OOP_GET_TAG_LO(oop)) - -#define MOO_OOP_IS_NUMERIC(oop) (MOO_OOP_GET_TAG_LO(oop) != 0) -#define MOO_OOP_IS_POINTER(oop) (MOO_OOP_GET_TAG_LO(oop) == 0) - -#define MOO_OOP_IS_SMOOI(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMOOI) -#define MOO_OOP_IS_SMPTR(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMPTR) - -#define MOO_SMOOI_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMOOI)) -#define MOO_OOP_TO_SMOOI(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO) -/* -#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)((((moo_oow_t)(ptr)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMPTR)) -#define MOO_OOP_TO_SMPTR(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO) -*/ -#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)(((moo_oow_t)ptr) | MOO_OOP_TAG_SMPTR)) -#define MOO_OOP_TO_SMPTR(oop) ((void*)(((moo_oow_t)oop) & ~MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO))) - -#define MOO_OOP_IS_CHAR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_CHAR) -#define MOO_OOP_IS_ERROR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_ERROR) - -#define MOO_OOP_TO_CHAR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) -#define MOO_CHAR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_CHAR)) -#define MOO_OOP_TO_ERROR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) -#define MOO_ERROR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_ERROR)) - -/* -------------------------------- */ - -/* SMOOI takes up 62 bits 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 sign bit. */ -#define MOO_SMOOI_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO) -#define MOO_SMOOI_ABS_BITS (MOO_SMOOI_BITS - 1) -#define MOO_SMOOI_MAX ((moo_ooi_t)(~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + 1))) -/* Sacrificing 1 bit pattern for a negative SMOOI makes - * implementation a lot eaisier in many aspects. */ -/*#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX - 1)*/ -#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX) -#define MOO_IN_SMOOI_RANGE(ooi) ((ooi) >= MOO_SMOOI_MIN && (ooi) <= MOO_SMOOI_MAX) - -/* SMPTR is a special value which has been devised to encode an address value - * whose low MOO_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 MOO_IN_SMPTR_RANGE(ptr) ((((moo_oow_t)ptr) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) == 0) - -#define MOO_CHAR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI) -#define MOO_CHAR_MIN 0 -#define MOO_CHAR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) - -#define MOO_ERROR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI) -#define MOO_ERROR_MIN 0 -#define MOO_ERROR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI)) - -/* TODO: There are untested code where a small integer is converted to moo_oow_t. - * for example, the spec making macro treats the number as moo_oow_t instead of moo_ooi_t. - * as of this writing, i skip testing that part with the spec value exceeding MOO_SMOOI_MAX. - * later, please verify it works, probably by limiting the value ranges in such macros - */ - -/* - * Object structure - */ +/* ========================================================================= + * OBJECT STRUCTURE + * ========================================================================= */ enum moo_obj_type_t { MOO_OBJ_TYPE_OOP, @@ -382,7 +294,7 @@ typedef enum moo_gcfin_t moo_gcfin_t; #define MOO_OBJ_FLAGS_KERNEL_BITS 2 #define MOO_OBJ_FLAGS_PERM_BITS 1 #define MOO_OBJ_FLAGS_MOVED_BITS 1 -#define MOO_OBJ_FLAGS_PROC_BITS 1 +#define MOO_OBJ_FLAGS_PROC_BITS 1 #define MOO_OBJ_FLAGS_RDONLY_BITS 1 #define MOO_OBJ_FLAGS_GCFIN_BITS 4 #define MOO_OBJ_FLAGS_TRAILER_BITS 1 @@ -1002,6 +914,11 @@ struct moo_fpdec_t #define MOO_BYTESOF(moo,oop) \ (MOO_OOP_IS_NUMERIC(oop)? MOO_SIZEOF(moo_oow_t): MOO_OBJ_BYTESOF(oop)) + +/* ========================================================================= + * HEAP + * ========================================================================= */ + typedef struct moo_space_t moo_space_t; struct moo_space_t @@ -1023,9 +940,8 @@ struct moo_heap_t moo_space_t newspace; }; - /* ========================================================================= - * MOO VM LOGGING + * VM LOGGING * ========================================================================= */ enum moo_log_mask_t diff --git a/moo/lib/sym.c b/moo/lib/sym.c index 58b2368..50570fd 100644 --- a/moo/lib/sym.c +++ b/moo/lib/sym.c @@ -75,7 +75,7 @@ static moo_oop_oop_t expand_bucket (moo_t* moo, moo_oop_oop_t oldbuc) MOO_ASSERT (moo, MOO_CLASSOF(moo,symbol) == moo->_symbol); /*MOO_ASSERT (moo, sym->size > 0);*/ - index = moo_hashoochars(MOO_OBJ_GET_CHAR_SLOT(symbol), MOO_OBJ_GET_SIZE(symbol)) % newsz; + index = moo_hash_oochars(MOO_OBJ_GET_CHAR_SLOT(symbol), MOO_OBJ_GET_SIZE(symbol)) % newsz; while (MOO_OBJ_GET_OOP_VAL(newbuc, index) != moo->_nil) index = (index + 1) % newsz; MOO_STORE_OOP (moo, MOO_OBJ_GET_OOP_PTR(newbuc, index), (moo_oop_t)symbol); } @@ -91,7 +91,7 @@ static moo_oop_t find_or_make_symbol (moo_t* moo, const moo_ooch_t* ptr, moo_oow moo_oop_char_t symbol; MOO_ASSERT (moo, MOO_CLASSOF(moo,moo->symtab->bucket) == moo->_array); - index = moo_hashoochars(ptr, len) % MOO_OBJ_GET_SIZE(moo->symtab->bucket); + index = moo_hash_oochars(ptr, len) % MOO_OBJ_GET_SIZE(moo->symtab->bucket); /* find a matching symbol in the open-addressed symbol table */ while ((moo_oop_t)(symbol = (moo_oop_char_t)MOO_OBJ_GET_OOP_VAL(moo->symtab->bucket, index)) != moo->_nil) @@ -146,7 +146,7 @@ static moo_oop_t find_or_make_symbol (moo_t* moo, const moo_ooch_t* ptr, moo_oow MOO_STORE_OOP (moo, (moo_oop_t*)&moo->symtab->bucket, (moo_oop_t)tmp); /* recalculate the index for the expanded bucket */ - index = moo_hashoochars(ptr, len) % MOO_OBJ_GET_SIZE(moo->symtab->bucket); + index = moo_hash_oochars(ptr, len) % MOO_OBJ_GET_SIZE(moo->symtab->bucket); while (MOO_OBJ_GET_OOP_VAL(moo->symtab->bucket, index) != moo->_nil) index = (index + 1) % MOO_OBJ_GET_SIZE(moo->symtab->bucket); diff --git a/moo/lib/utl.c b/moo/lib/utl.c index 9c13c17..35c07ae 100644 --- a/moo/lib/utl.c +++ b/moo/lib/utl.c @@ -206,6 +206,16 @@ moo_uint128_t moo_hton128 (moo_uint128_t x) /* ----------------------------------------------------------------------- */ +moo_oow_t moo_hash_bytes_ (const moo_oob_t* ptr, moo_oow_t len) +{ + moo_oow_t hv; + MOO_HASH_BYTES (hv, ptr, len); + /* constrain the hash value to be representable in a small integer + * for convenience sake */ + return hv % ((moo_oow_t)MOO_SMOOI_MAX + 1); +} + +/* ----------------------------------------------------------------------- */ /* some naming conventions * bchars, uchars -> pointer and length @@ -216,51 +226,6 @@ moo_uint128_t moo_hton128 (moo_uint128_t x) * utobcstr -> ucstr to bcstr */ - -#if MOO_SIZEOF_OOW_T == 4 -# define FNV_MAGIC_INIT (0x811c9dc5) -# define FNV_MAGIC_PRIME (0x01000193) -#elif MOO_SIZEOF_OOW_T == 8 -# define FNV_MAGIC_INIT (0xCBF29CE484222325) -# define FNV_MAGIC_PRIME (0x100000001B3) -#elif MOO_SIZEOF_OOW_T == 16 -# define FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) -# define FNV_MAGIC_PRIME (0x1000000000000000000013B) -#endif - -moo_oow_t moo_hash_bytes (const moo_oob_t* ptr, moo_oow_t len) -{ - moo_oow_t h; - const moo_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 ^= (moo_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 - - /* constrain the hash value to be representable in a small integer - * for convenience sake */ - return h % ((moo_oow_t)MOO_SMOOI_MAX + 1); -} - int moo_equal_uchars (const moo_uch_t* str1, const moo_uch_t* str2, moo_oow_t len) { moo_oow_t i;