Sigrid Solveig HaflínudóttirWIP unboxed short strings90838aa1 year agoHistory
1571 lines · 33.0 KB · C
RawDownload
#include "sl.h"#include "operators.h"#include "cvalues.h"#include "types.h"#include "io.h"#include "equal.h" enum {	MAX_INL_SIZE = 384,	CVALUE_NWORDS = sizeof(sl_cv)/sizeof(sl_v), 	CV_OWNED = 1<<0,}; #define owned(cv) ((uintptr)(cv)->type & CV_OWNED)#define isinlined(cv) ((cv)->data == (cv)->_space) sl_type *unboxedtypes[T_UNBOXED_NUM];sl_v unboxedtypesyms[T_UNBOXED_NUM]; static void cvalue_init(sl_type *type, sl_v v, void *dest); voidadd_finalizer(sl_cv *cv){	if(slg.nfinalizers == slg.maxfinalizers){		slg.maxfinalizers *= 2;		slg.finalizers = MEM_REALLOC(slg.finalizers, slg.maxfinalizers*sizeof(slg.finalizers));		assert(slg.finalizers != nil);	}	slg.finalizers[slg.nfinalizers++] = cv;} // remove dead objects from finalization list in-placevoidsweep_finalizers(void){	sl_cv **lst = slg.finalizers;	usize n = 0, ndel = 0, l = slg.nfinalizers;	sl_cv *tmp;#define SWAP_sf(a, b) (tmp = a, a = b, b = tmp, 1)	if(l == 0)		return;	do{		tmp = lst[n];		if(isforwarded((sl_v)tmp)){			// object is alive			lst[n] = ptr(forwardloc((sl_v)tmp));			n++;		}else{			sl_type *t = cv_class(tmp);			if(t->vtable != nil && t->vtable->finalize != nil)				t->vtable->finalize(tagptr(tmp, TAG_CVALUE));			if(!isinlined(tmp) && owned(tmp))				MEM_FREE(cv_data(tmp));			ndel++;		}	}while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel])); 	slg.nfinalizers -= ndel;	slg.malloc_pressure = 0;} char *tostr(sl_v v, usize *sz, sl_v *tmp){	if(isubstr(v)){		if(sz != nil)			*sz = ubstrsz(v);		*tmp = v >> 8;		return (char*)tmp;	}	if(iscvalue(v) && cv_isstr(ptr(v))){		if(sz != nil)			*sz = cv_len(ptr(v));		return cvalue_data(v);	}	type_error("str", v);} // compute the size of the metadata object for a cvaluestatic usizecv_nwords(sl_cv *cv){	if(!isinlined(cv))		return CVALUE_NWORDS;	usize n = cv_len(cv);	if(cv_isstr(cv))		n++;	return CVALUE_NWORDS + NWORDS(n);} voidcv_autorelease(sl_cv *cv){	cv->type = (sl_type*)(((uintptr)cv->type) | CV_OWNED);	add_finalizer(cv);} static sl_vcprim(sl_type *type, usize sz){	assert(!ismanaged((uintptr)type));	assert(sz == type->size);	sl_cprim *pcp = alloc_words(CPRIM_NWORDS+NWORDS(sz));	pcp->type = type;	return tagptr(pcp, TAG_CPRIM);} sl_vcvalue_(sl_type *type, usize sz, bool nofinalize){	assert(type != nil);	if(valid_numtype(type->numtype) && type->numtype != T_MP)		return cprim(type, sz); 	bool str = false;	if(type->eltype == sl_utf8type){		if(sz == 0)			return sl_emptystr;		sz++;		str = true;	}	sl_cv *pcv;	if(sz <= MAX_INL_SIZE){		usize nw = CVALUE_NWORDS + NWORDS(sz);		pcv = alloc_words(nw);		pcv->type = type;		pcv->data = pcv->_space;		if(!nofinalize && type->vtable != nil && type->vtable->finalize != nil)			add_finalizer(pcv);	}else{		if(slg.malloc_pressure > ALLOC_LIMIT_TRIGGER)			sl_gc(false);		pcv = alloc_words(CVALUE_NWORDS);		pcv->type = type;		pcv->data = MEM_ALLOC(sz);		cv_autorelease(pcv);		slg.malloc_pressure += sz;	}	if(str)		((char*)pcv->data)[--sz] = '\0';	pcv->len = sz;	return tagptr(pcv, TAG_CVALUE);} // this effectively dereferences a pointer// just like *p in C, it only removes a level of indirection from the type,// it doesn't copy any data.// this method of creating a cvalue only allocates metadata.// ptr is user-managed; we don't autorelease it unless the// user explicitly calls (autorelease ) on the result of this function.// 'parent' is an optional cvalue that this pointer is known to point// into; NIL if none.sl_vcvalue_from_ref(sl_type *type, void *ptr, usize sz){	sl_cv *pcv; 	assert(type != nil);	assert(ptr != nil);	pcv = alloc_words(CVALUE_NWORDS);	pcv->data = ptr;	pcv->len = sz;	pcv->type = type;	return tagptr(pcv, TAG_CVALUE);} sl_vcvalue_str(usize n){	if(n <= UBSTR_MAX){		sl_v v = n<<5 | TAG_UBSTR;		return v;	}	return cvalue(sl_strtype, n);} sl_vcvalue_static_cstr(const char *str){	usize n = strlen(str);	if(n <= UBSTR_MAX){		sl_v v = n<<5 | TAG_UBSTR;		memcpy(ubstr(v), str, n);		return v;	}	return cvalue_from_ref(sl_strtype, (char*)str, n);} sl_vstr_from_cstrn(char *str, usize n){	sl_v v;	if(n <= UBSTR_MAX){		v = n<<5 | TAG_UBSTR;		memcpy(ubstr(v), str, n);	}else{		v = cvalue(sl_strtype, n);		memcpy(cvalue_data(v), str, n);	}	return v;} sl_vstr_from_cstr(char *str){	return str_from_cstrn(str, strlen(str));} boolsl_isstr(sl_v v){	return isubstr(v) || (iscvalue(v) && cv_isstr(ptr(v)));} // convert to malloc representation (fixed address)voidcv_pin(sl_cv *cv){	if(!isinlined(cv))		return;	usize n = cv_len(cv);	if(cv_isstr(cv))		n++;	void *data = MEM_ALLOC(n);	memcpy(data, cv_data(cv), n);	cv->data = data;	cv_autorelease(cv);} static voidcvalue_rune_init(sl_type *type, sl_v a, void *dest){	Rune r;	USED(type);	if(isfixnum(a)){		r = numval(a);	}else if(isrune(a)){		r = torune(a);	}else if(isubnumu(a)){		uintptr v = ubnumuval(a);		r = conv_to_u32(&v, ubnumtype(a));	}else if(isubnums(a)){		intptr v = ubnumsval(a);		r = conv_to_u32(&v, ubnumtype(a));	}else if(iscprim(a)){		sl_cprim *cp = ptr(a);		r = conv_to_u32(cp_data(cp), cp_numtype(cp));	}else if(ismp(a)){		r = conv_to_u32(cv_data(ptr(a)), T_MP);	}else		type_error("num", a);	*((Rune*)dest) = r;} #define num_init(ctype, cnvt, tag) \	static void \	cvalue_##ctype##_init(sl_type *type, sl_v a, void *dest) \	{ \		ctype n; \		USED(type); \		if(isfixnum(a)){ \			n = (ctype)numval(a); \		}else if(isubnumu(a)){ \			uintptr v = ubnumuval(a); \			n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \		}else if(isubnums(a)){ \			intptr v = ubnumsval(a); \			n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \		}else if(iscprim(a)){ \			sl_cprim *cp = ptr(a); \			n = (ctype)conv_to_##cnvt(cp_data(cp), cp_numtype(cp)); \		}else if(ismp(a)){ \			n = (ctype)conv_to_##cnvt(cv_data(ptr(a)), T_MP); \		}else \			type_error("num", a); \		*((ctype*)dest) = n; \	} num_init(s8int, s32, T_S8)num_init(u8int, u32, T_U8)num_init(s16int, s32, T_S16)num_init(u16int, u32, T_U16)num_init(s32int, s32, T_S32)num_init(u32int, u32, T_U32)num_init(s64int, s64, T_S64)num_init(u64int, u64, T_U64)num_init(float, double, T_FLOAT)num_init(double, double, T_DOUBLE) BUILTIN("rune", rune){	if(nargs == 0){		PUSH(fixnum(0));		args = sl.sp-1;	}	Rune r;	cvalue_rune_init(sl_runetype, args[0], &r);	return mk_rune(r);} #define num_ctor_init(typenam, ctype, tag) \	static \	BUILTIN(#typenam, typenam) \	{ \		if(nargs == 0){ \			PUSH(fixnum(0)); \			args = sl.sp-1; \		} \		sl_v v = cprim(sl_##typenam##type, sizeof(ctype)); \		cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \		return v; \	} #define num_ctor_init_unboxed(typenam, ctype, tag) \	static \	BUILTIN(#typenam, typenam) \	{ \		if(nargs == 0){ \			PUSH(fixnum(0)); \			args = sl.sp-1; \		} \		sl_v v; \		if(tag < T_UNBOXED_NUM && \		   sizeof(ctype) < sizeof(sl_v)){ \			ctype u; \			cvalue_##ctype##_init(sl_##typenam##type, args[0], &u); \			v = (sl_v)u<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \		}else{ \			v = cprim(sl_##typenam##type, sizeof(ctype)); \			cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \		} \		return v; \	} #define num_ctor_ctor(typenam, ctype, tag) \	sl_v \	mk_##typenam(ctype n) \	{ \		sl_v v = cprim(sl_##typenam##type, sizeof(n)); \		*(ctype*)cp_data(ptr(v)) = n; \		return v; \	} #define num_ctor_ctor_unboxed(typenam, ctype, tag) \	sl_constfn \	sl_v \	mk_##typenam(ctype n) \	{ \		sl_v v; \		if(tag < T_UNBOXED_NUM && \		   (sizeof(n) < sizeof(sl_v) || fits_bits(n, UNBOXED_BITS))){ \			v = n<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \		}else{ \			v = cprim(sl_##typenam##type, sizeof(n)); \			*(ctype*)cp_data(ptr(v)) = n; \		} \		return v; \	} #define num_ctor(typenam, ctype, tag) \	num_ctor_init(typenam, ctype, tag) \	num_ctor_ctor(typenam, ctype, tag) #define num_ctor_unboxed(typenam, ctype, tag) \	num_ctor_init_unboxed(typenam, ctype, tag) \	num_ctor_ctor_unboxed(typenam, ctype, tag) num_ctor_init_unboxed(s8, s8int, T_S8)num_ctor_init_unboxed(u8, u8int, T_U8)num_ctor_init_unboxed(s16, s16int, T_S16)num_ctor_init_unboxed(u16, u16int, T_U16)num_ctor_unboxed(s32, s32int, T_S32)num_ctor_unboxed(u32, u32int, T_U32)num_ctor_unboxed(s64, s64int, T_S64)num_ctor_unboxed(u64, u64int, T_U64)num_ctor_init(utf8, u8int, T_U8)num_ctor(float, float, T_FLOAT)num_ctor(double, double, T_DOUBLE) static voidcvalue_mp_init(sl_type *type, sl_v a, void *dest){	mpint *n;	USED(type);	if(isfixnum(a))		n = vtomp(numval(a), nil);	else if(isubnum(a)){		uintptr v;		void *p = &v;		if(isubnumu(a))			v = ubnumuval(a);		else			v = ubnumsval(a);		n = conv_to_mp(p, ubnumtype(a));	}else if(iscvalue(a)){		sl_cv *cv = ptr(a);		void *p = cv_data(cv);		n = conv_to_mp(p, cv_numtype(cv));	}else if(iscprim(a)){		sl_cprim *cp = ptr(a);		void *p = cp_data(cp);		n = conv_to_mp(p, cp_numtype(cp));	}else		type_error("num", a);	*((mpint**)dest) = n;} BUILTIN("bignum", bignum){	if(nargs == 0){		PUSH(fixnum(0));		args = sl.sp-1;	}	sl_v cv = cvalue(sl_mptype, sizeof(mpint*));	cvalue_mp_init(sl_mptype, args[0], cvalue_data(cv));	return cv;}  sl_vmk_mp(mpint *n){	sl_v cv = cvalue(sl_mptype, sizeof(mpint*));	*(mpint**)cvalue_data(cv) = n;	return cv;} static voidfree_mp(sl_v self){	mpint **s = value2c(mpint**, self);	if(*s != mpzero && *s != mpone && *s != mptwo)		mpfree(*s);} static sl_cvtable mp_vtable = { nil, nil, free_mp, nil }; sl_constfnsl_vsize_wrap(usize sz){	if(sizeof(usize) == 8)		return fits_fixnum(sz) ? fixnum(sz): mk_u64(sz);	else		return fits_fixnum(sz) ? fixnum(sz): mk_u32(sz);} usizetosize(sl_v n){	if(isfixnum(n))		return (usize)numval(n);	if(isubnum(n))		return (usize)ubnumuval(n);	if(iscprim(n)){		sl_cprim *cp = ptr(n);		if(sizeof(usize) == 8)			return conv_to_u64(cp_data(cp), cp_numtype(cp));		return conv_to_u32(cp_data(cp), cp_numtype(cp));	}	type_error("num", n);} soffsettooffset(sl_v n){	if(isfixnum(n))		return numval(n);	if(isubnumu(n))		return ubnumuval(n);	if(isubnums(n))		return ubnumsval(n);	if(iscprim(n)){		sl_cprim *cp = ptr(n);		return conv_to_s64(cp_data(cp), cp_numtype(cp));	}	type_error("num", n);} boolisarr(sl_v v){	return iscvalue(v) && cv_class(ptr(v))->eltype != nil;} static usizepredict_arrlen(sl_v arg){	if(isvec(arg))		return vec_size(arg);	if(iscons(arg))		return llength(arg);	if(arg == sl_nil)		return 0;	if(isarr(arg))		return cvalue_arrlen(arg);	return 1;}

Lines 1–500 of 1571.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t