shithub: femtolisp

Download patch

ref: d170d141ad95660edfdd8dca4bebe9d7b4485197
parent: da7de7d9c3f9c66468e4d988cc6b23bc961ed742
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Sat Nov 9 11:56:04 EST 2024

vm loop: update current frame's instruction pointer before any exceptions may be raised

--- a/cvalues.c
+++ b/cvalues.c
@@ -978,7 +978,7 @@
 	int64_t Saccum = carryIn;
 	int64_t Sresult;
 	double Faccum = 0;
-	int32_t inexact = 0;
+	bool inexact = false;
 	uint32_t i;
 	int64_t i64;
 	value_t arg;
@@ -1039,8 +1039,8 @@
 					Maccum = mpnew(0);
 				mpadd(Maccum, *(mpint**)a, Maccum);
 				break;
-			case T_FLOAT:  Faccum += *(float*)a; inexact = 1; break;
-			case T_DOUBLE: Faccum += *(double*)a; inexact = 1; break;
+			case T_FLOAT:  Faccum += *(float*)a; inexact = true; break;
+			case T_DOUBLE: Faccum += *(double*)a; inexact = true; break;
 			default:
 				goto add_type_error;
 			}
@@ -1152,11 +1152,12 @@
 }
 
 value_t
-fl_mul_any(value_t *args, uint32_t nargs, int64_t Saccum)
+fl_mul_any(value_t *args, uint32_t nargs)
 {
+	int64_t Saccum = 1;
 	uint64_t Uaccum = 1;
 	double Faccum = 1;
-	int32_t inexact = 0;
+	bool inexact = false;
 	int64_t i64;
 	uint32_t i;
 	value_t arg;
@@ -1191,8 +1192,8 @@
 					Maccum = mpcopy(mpone);
 				mpmul(Maccum, *(mpint**)a, Maccum);
 				break;
-			case T_FLOAT:  Faccum *= *(float*)a; inexact = 1; break;
-			case T_DOUBLE: Faccum *= *(double*)a; inexact = 1; break;
+			case T_FLOAT:  Faccum *= *(float*)a; inexact = true; break;
+			case T_DOUBLE: Faccum *= *(double*)a; inexact = true; break;
 			default:
 				goto mul_type_error;
 			}
--- a/cvalues.h
+++ b/cvalues.h
@@ -48,7 +48,7 @@
 value_t return_from_int64(int64_t Saccum);
 value_t fl_add_any(value_t *args, uint32_t nargs, fixnum_t carryIn);
 value_t fl_neg(value_t n);
-value_t fl_mul_any(value_t *args, uint32_t nargs, int64_t Saccum);
+value_t fl_mul_any(value_t *args, uint32_t nargs);
 int num_to_ptr(value_t a, fixnum_t *pi, numerictype_t *pt, void **pp);
 int numeric_compare(value_t a, value_t b, int eq, int eqnans, int typeerr);
 _Noreturn void DivideByZeroError(void);
--- a/flisp.c
+++ b/flisp.c
@@ -148,7 +148,7 @@
 #define SAFECAST_OP(type, ctype, cnvt) \
 	ctype to##type(value_t v) \
 	{ \
-		if(is##type(v)) \
+		if(__likely(is##type(v))) \
 			return (ctype)cnvt(v); \
 		type_error(#type, v); \
 	}
@@ -318,7 +318,7 @@
 void
 fl_gc_handle(value_t *pv)
 {
-	if(fl->N_GCHND >= N_GC_HANDLES)
+	if(__unlikely(fl->N_GCHND >= N_GC_HANDLES))
 		lerrorf(fl->MemoryError, "out of gc handles");
 	fl->GCHandleStack[fl->N_GCHND++] = pv;
 }
@@ -509,13 +509,13 @@
 	// grow the other half of the heap this time to catch up.
 	if(fl->grew || ((fl->lim-fl->curheap) < (int)(fl->heapsize/5)) || mustgrow){
 		temp = LLT_REALLOC(fl->tospace, fl->heapsize*2);
-		if(temp == nil)
+		if(__unlikely(temp == nil))
 			fl_raise(fl->memory_exception_value);
 		fl->tospace = temp;
 		if(fl->grew){
 			fl->heapsize *= 2;
 			temp = bitvector_resize(fl->consflags, 0, fl->heapsize/sizeof(cons_t), 1);
-			if(temp == nil)
+			if(__unlikely(temp == nil))
 				fl_raise(fl->memory_exception_value);
 			fl->consflags = (uint32_t*)temp;
 		}
@@ -530,7 +530,7 @@
 {
 	size_t newsz = fl->N_STACK * 2;
 	value_t *ns = LLT_REALLOC(fl->Stack, newsz*sizeof(value_t));
-	if(ns == nil)
+	if(__unlikely(ns == nil))
 		lerrorf(fl->MemoryError, "stack overflow");
 	fl->Stack = ns;
 	fl->N_STACK = newsz;
@@ -549,9 +549,9 @@
 		v = ((builtin_t*)ptr(f))[3](&fl->Stack[fl->SP-n], n);
 	}else if(isfunction(f)){
 		v = apply_cl(n);
-	}else if(isbuiltin(f)){
+	}else if(__likely(isbuiltin(f))){
 		value_t tab = symbol_value(fl->builtins_table_sym);
-		if(ptr(tab) == nil)
+		if(__unlikely(ptr(tab) == nil))
 			unbound_error(tab);
 		fl->Stack[fl->SP-n-1] = vector_elt(tab, uintval(f));
 		v = apply_cl(n);
@@ -589,7 +589,7 @@
 	size_t i;
 
 	PUSH(f);
-	while(fl->SP+n > fl->N_STACK)
+	while(fl->SP+n >= fl->N_STACK)
 		grow_stack();
 	for(i = 0; i < n; i++){
 		value_t a = va_arg(ap, value_t);
@@ -609,7 +609,7 @@
 	uint32_t si = fl->SP;
 	size_t i;
 
-	while(fl->SP+n > fl->N_STACK)
+	while(fl->SP+n >= fl->N_STACK)
 		grow_stack();
 	for(i = 0; i < n; i++){
 		value_t a = va_arg(ap, value_t);
@@ -687,9 +687,9 @@
 		c++;
 	}
 	if(star)
-		(c-2)->cdr = (c-1)->car;
+		c[-2].cdr = c[-1].car;
 	else
-		(c-1)->cdr = fl->NIL;
+		c[-1].cdr = fl->NIL;
 	return v;
 }
 
@@ -758,9 +758,9 @@
 	value_t s2 = fl->Stack[fl->SP-2];
 	value_t s4 = fl->Stack[fl->SP-4];
 	value_t s5 = fl->Stack[fl->SP-5];
-	if(nargs < nreq)
+	if(__unlikely(nargs < nreq))
 		lerrorf(fl->ArgError, "too few arguments");
-	if(extr > nelem(args))
+	if(__unlikely(extr > nelem(args)))
 		lerrorf(fl->ArgError, "too many arguments");
 	for(i = 0; i < extr; i++)
 		args[i] = UNBOUND;
@@ -778,12 +778,12 @@
 	uintptr_t n = vector_size(kwtable)/2;
 	do{
 		i++;
-		if(i >= nargs)
+		if(__unlikely(i >= nargs))
 			lerrorf(fl->ArgError, "keyword %s requires an argument", symbol_name(v));
 		value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
 		lltint_t lx = numval(hv);
 		uintptr_t x = 2*((lx < 0 ? -lx : lx) % n);
-		if(vector_elt(kwtable, x) == v){
+		if(__likely(vector_elt(kwtable, x) == v)){
 			uintptr_t idx = numval(vector_elt(kwtable, x+1));
 			assert(idx < nkw);
 			idx += nopt;
@@ -801,7 +801,7 @@
 	}while(issymbol(v) && iskeyword((symbol_t*)ptr(v)));
 no_kw:
 	nrestargs = nargs - i;
-	if(!va && nrestargs > 0)
+	if(__unlikely(!va && nrestargs > 0))
 		lerrorf(fl->ArgError, "too many arguments");
 	nargs = ntot + nrestargs;
 	if(nrestargs)
@@ -864,11 +864,10 @@
 	int tail, x;
 
 	// temporary variables (not necessary to preserve across calls)
-	uint32_t op, i;
+	uint32_t op, i, ipd;
 	symbol_t *sym;
 	cons_t *c;
 	value_t *pv;
-	int64_t accum;
 	value_t func, v, e;
 
 	n = 0;
@@ -880,7 +879,8 @@
 	func = fl->Stack[fl->SP-nargs-1];
 	ip = cv_data((cvalue_t*)ptr(fn_bcode(func)));
 	assert(!ismanaged((uintptr_t)ip));
-	while(fl->SP+GET_INT32(ip) > fl->N_STACK)
+	i = fl->SP+GET_INT32(ip);
+	while(i >= fl->N_STACK)
 		grow_stack();
 	ip += 4;
 
@@ -888,8 +888,9 @@
 	PUSH(fn_env(func));
 	PUSH(fl->curr_frame);
 	PUSH(nargs);
-	fl->SP++;//PUSH(0); //ip
-	PUSH(0); //captured?
+	ipd = fl->SP;
+	fl->SP++; // ip
+	PUSH(0); // captured?
 	fl->curr_frame = fl->SP;
 
 	op = *ip++;
@@ -935,6 +936,7 @@
 				n = *ip++;  // nargs
 			}
 		do_call:
+			fl->Stack[ipd] = (uintptr_t)ip;
 			func = fl->Stack[fl->SP-n-1];
 			if(tag(func) == TAG_FUNCTION){
 				if(func > (N_BUILTINS<<3)){
@@ -943,8 +945,6 @@
 						for(s = -1; s < (fixnum_t)n; s++)
 							fl->Stack[bp+s] = fl->Stack[fl->SP-n+s];
 						fl->SP = bp+n;
-					}else{
-						fl->Stack[fl->curr_frame-2] = (uintptr_t)ip;
 					}
 					nargs = n;
 					goto apply_cl_top;
@@ -974,7 +974,7 @@
 						}
 					}
 				}
-			}else if(iscbuiltin(func)){
+			}else if(__likely(iscbuiltin(func))){
 				s = fl->SP;
 				v = (((builtin_t*)ptr(func))[3])(&fl->Stack[fl->SP-n], n);
 				fl->SP = s-n;
@@ -996,8 +996,10 @@
 			}
 			assert(issymbol(v));
 			sym = (symbol_t*)ptr(v);
-			if(sym->binding == UNBOUND)
+			if(__unlikely(sym->binding == UNBOUND)){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				unbound_error(v);
+			}
 			PUSH(sym->binding);
 			NEXT_OP;
 
@@ -1034,7 +1036,8 @@
 				return v;
 			fl->SP -= 5+nargs;
 			captured = fl->Stack[fl->curr_frame-1];
-			ip = (uint8_t*)fl->Stack[fl->curr_frame-2];
+			ipd = fl->curr_frame-2;
+			ip = (uint8_t*)fl->Stack[ipd];
 			nargs = fl->Stack[fl->curr_frame-3];
 			bp = fl->curr_frame - 5 - nargs;
 			fl->Stack[fl->SP-1] = v;
@@ -1047,15 +1050,19 @@
 
 		OP(OP_CAR)
 			v = fl->Stack[fl->SP-1];
-			if(!iscons(v))
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				type_error("cons", v);
+			}
 			fl->Stack[fl->SP-1] = car_(v);
 			NEXT_OP;
 
 		OP(OP_CDR)
 			v = fl->Stack[fl->SP-1];
-			if(!iscons(v))
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				type_error("cons", v);
+			}
 			fl->Stack[fl->SP-1] = cdr_(v);
 			NEXT_OP;
 
@@ -1082,7 +1089,7 @@
 			if(fl->curheap > fl->lim-2)
 				gc(0);
 			pv = (value_t*)fl->curheap;
-			fl->curheap += (4*sizeof(value_t));
+			fl->curheap += 4*sizeof(value_t);
 			e = fl->Stack[fl->SP-2];  // closure to copy
 			assert(isfunction(e));
 			pv[0] = ((value_t*)ptr(e))[0];
@@ -1137,14 +1144,15 @@
 			NEXT_OP;
 
 		OP(OP_AREF)
+			fl->Stack[ipd] = (uintptr_t)ip;
 			v = fl->Stack[fl->SP-2];
 			if(isvector(v)){
 				e = fl->Stack[fl->SP-1];
 				i = isfixnum(e) ? numval(e) : (uint32_t)toulong(e);
-				if(i >= vector_size(v))
+				if(__unlikely(i >= vector_size(v)))
 					bounds_error(v, e);
 				v = vector_elt(v, i);
-			}else if(isarray(v)){
+			}else if(__likely(isarray(v))){
 				v = cvalue_array_aref(&fl->Stack[fl->SP-2]);
 			}else{
 				type_error("sequence", v);
@@ -1178,6 +1186,7 @@
 			NEXT_OP;
 
 		OP(OP_ADD2)
+			fl->Stack[ipd] = (uintptr_t)ip;
 			if(bothfixnums(fl->Stack[fl->SP-1], fl->Stack[fl->SP-2])){
 				s = numval(fl->Stack[fl->SP-1]) + numval(fl->Stack[fl->SP-2]);
 				v = fits_fixnum(s) ? fixnum(s) : mk_xlong(s);
@@ -1189,7 +1198,12 @@
 			NEXT_OP;
 
 		OP(OP_SETCDR)
-			cdr(fl->Stack[fl->SP-2]) = fl->Stack[fl->SP-1];
+			v = fl->Stack[fl->SP-2];
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
+				type_error("cons", v);
+			}
+			cdr_(v) = fl->Stack[fl->SP-1];
 			POPN(1);
 			NEXT_OP;
 
@@ -1205,7 +1219,8 @@
 			c->car = fl->Stack[fl->SP-2];
 			c->cdr = fl->Stack[fl->SP-1];
 			fl->Stack[fl->SP-2] = tagptr(c, TAG_CONS);
-			POPN(1); NEXT_OP;
+			POPN(1);
+			NEXT_OP;
 
 		OP(OP_EQ)
 			fl->Stack[fl->SP-2] = fl->Stack[fl->SP-2] == fl->Stack[fl->SP-1] ? fl->FL_T : fl->FL_F;
@@ -1222,16 +1237,21 @@
 
 		OP(OP_CADR)
 			v = fl->Stack[fl->SP-1];
-			if(!iscons(v))
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				type_error("cons", v);
+			}
 			v = cdr_(v);
-			if(!iscons(v))
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				type_error("cons", v);
+			}
 			fl->Stack[fl->SP-1] = car_(v);
 			NEXT_OP;
 
 		OP(OP_NEG)
 		do_neg:
+			fl->Stack[ipd] = (uintptr_t)ip;
 			fl->Stack[fl->SP-1] = fl_neg(fl->Stack[fl->SP-1]);
 			NEXT_OP;
 
@@ -1254,6 +1274,7 @@
 			NEXT_OP;
 
 		OP(OP_BOUNDP)
+			fl->Stack[ipd] = (uintptr_t)ip;
 			sym = tosymbol(fl->Stack[fl->SP-1]);
 			fl->Stack[fl->SP-1] = sym->binding == UNBOUND ? fl->FL_F : fl->FL_T;
 			NEXT_OP;
@@ -1265,9 +1286,10 @@
 
 		OP(OP_FUNCTIONP)
 			v = fl->Stack[fl->SP-1];
-			fl->Stack[fl->SP-1] = ((tag(v) == TAG_FUNCTION &&
-							(isbuiltin(v) || v>(N_BUILTINS<<3))) ||
-						   iscbuiltin(v)) ? fl->FL_T : fl->FL_F;
+			fl->Stack[fl->SP-1] =
+				((tag(v) == TAG_FUNCTION &&
+				  (isbuiltin(v) || v>(N_BUILTINS<<3))) ||
+				 iscbuiltin(v)) ? fl->FL_T : fl->FL_F;
 			NEXT_OP;
 
 		OP(OP_VECTORP)
@@ -1324,7 +1346,12 @@
 			NEXT_OP;
 
 		OP(OP_SETCAR)
-			car(fl->Stack[fl->SP-2]) = fl->Stack[fl->SP-1];
+			v = fl->Stack[fl->SP-2];
+			if(__unlikely(!iscons(v))){
+				fl->Stack[ipd] = (uintptr_t)ip;
+				type_error("cons", v);
+			}
+			car_(v) = fl->Stack[fl->SP-1];
 			POPN(1);
 			NEXT_OP;
 
@@ -1367,12 +1394,13 @@
 			for(; i < fl->SP; i++){
 				if(isfixnum(fl->Stack[i])){
 					s += numval(fl->Stack[i]);
-					if(!fits_fixnum(s)){
+					if(__unlikely(!fits_fixnum(s))){
 						i++;
 						goto add_ovf;
 					}
 				}else{
 				add_ovf:
+					fl->Stack[ipd] = (uintptr_t)ip;
 					v = fl_add_any(&fl->Stack[i], fl->SP-i, s);
 					break;
 				}
@@ -1390,6 +1418,7 @@
 				goto do_sub2;
 			if(n == 1)
 				goto do_neg;
+			fl->Stack[ipd] = (uintptr_t)ip;
 			i = fl->SP-n;
 			// we need to pass the full arglist on to fl_add_any
 			// so it can handle rest args properly
@@ -1408,6 +1437,7 @@
 				s = numval(fl->Stack[fl->SP-2]) - numval(fl->Stack[fl->SP-1]);
 				v = fits_fixnum(s) ? fixnum(s) : mk_xlong(s);
 			}else{
+				fl->Stack[ipd] = (uintptr_t)ip;
 				fl->Stack[fl->SP-1] = fl_neg(fl->Stack[fl->SP-1]);
 				v = fl_add_any(&fl->Stack[fl->SP-2], 2, 0);
 			}
@@ -1418,17 +1448,8 @@
 		OP(OP_MUL)
 			n = *ip++;
 		apply_mul:
-			accum = 1;
-			for(i = fl->SP-n; i < fl->SP; i++){
-				if(isfixnum(fl->Stack[i])){
-					accum *= numval(fl->Stack[i]);
-				}else{
-					v = fl_mul_any(&fl->Stack[i], fl->SP-i, accum);
-					break;
-				}
-			}
-			if(i == fl->SP)
-				v = fits_fixnum(accum) ? fixnum(accum) : return_from_int64(accum);
+			fl->Stack[ipd] = (uintptr_t)ip;
+			v = fl_mul_any(&fl->Stack[fl->SP-n], n);
 			POPN(n);
 			PUSH(v);
 			NEXT_OP;
@@ -1436,6 +1457,7 @@
 		OP(OP_DIV)
 			n = *ip++;
 		apply_div:
+			fl->Stack[ipd] = (uintptr_t)ip;
 			i = fl->SP-n;
 			if(n == 1){
 				fl->Stack[fl->SP-1] = fl_div2(fixnum(1), fl->Stack[i]);
@@ -1443,7 +1465,7 @@
 				if(n > 2){
 					PUSH(fl->Stack[i]);
 					fl->Stack[i] = fixnum(1);
-					fl->Stack[i+1] = fl_mul_any(&fl->Stack[i], n, 1);
+					fl->Stack[i+1] = fl_mul_any(&fl->Stack[i], n);
 					fl->Stack[i] = POP();
 				}
 				v = fl_div2(fl->Stack[i], fl->Stack[i+1]);
@@ -1453,13 +1475,16 @@
 			NEXT_OP;
 
 		OP(OP_IDIV)
-			v = fl->Stack[fl->SP-2]; e = fl->Stack[fl->SP-1];
+			fl->Stack[ipd] = (uintptr_t)ip;
+			v = fl->Stack[fl->SP-2];
+			e = fl->Stack[fl->SP-1];
 			if(bothfixnums(v, e)){
 				if(e == 0)
 					DivideByZeroError();
 				v = fixnum(numval(v) / numval(e));
-			}else
+			}else{
 				v = fl_idiv2(v, e);
+			}
 			POPN(1);
 			fl->Stack[fl->SP-1] = v;
 			NEXT_OP;
@@ -1468,8 +1493,10 @@
 			v = fl->Stack[fl->SP-2]; e = fl->Stack[fl->SP-1];
 			if(bothfixnums(v, e))
 				v = v == e ? fl->FL_T : fl->FL_F;
-			else
+			else{
+				fl->Stack[ipd] = (uintptr_t)ip;
 				v = numeric_compare(v, e, 1, 0, 1) == 0 ? fl->FL_T : fl->FL_F;
+			}
 			POPN(1);
 			fl->Stack[fl->SP-1] = v;
 			NEXT_OP;
@@ -1486,6 +1513,7 @@
 				n = GET_INT32(ip);
 				ip += 4;
 			}
+			fl->Stack[ipd] = (uintptr_t)ip;
 			argcount(nargs, n);
 			NEXT_OP;
 
@@ -1502,12 +1530,13 @@
 
 		OP(OP_ASET)
 			e = fl->Stack[fl->SP-3];
+			fl->Stack[ipd] = (uintptr_t)ip;
 			if(isvector(e)){
 				i = tofixnum(fl->Stack[fl->SP-2]);
-				if(i >= vector_size(e))
+				if(__unlikely(i >= vector_size(e)))
 					bounds_error(v, fl->Stack[fl->SP-1]);
 				vector_elt(e, i) = (v = fl->Stack[fl->SP-1]);
-			}else if(isarray(e)){
+			}else if(__likely(isarray(e))){
 				v = cvalue_array_aset(&fl->Stack[fl->SP-3]);
 			}else{
 				type_error("sequence", e);
@@ -1517,9 +1546,9 @@
 			NEXT_OP;
 
 		OP(OP_FOR)
+			fl->Stack[ipd] = (uintptr_t)ip;
 			s  = tofixnum(fl->Stack[fl->SP-3]);
 			hi = tofixnum(fl->Stack[fl->SP-2]);
-			//f = fl->Stack[fl->SP-1];
 			v = fl->FL_UNSPECIFIED;
 			fl->SP += 2;
 			n = fl->SP;
@@ -1640,7 +1669,8 @@
 					fl->SP =  bp+i+6;
 					fl->curr_frame = fl->SP;
 				}
-			}else if(s < 0){
+			}else if(__unlikely(s < 0)){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				lerrorf(fl->ArgError, "too few arguments");
 			}else{
 				PUSH(0);
@@ -1650,10 +1680,12 @@
 				fl->Stack[fl->SP-6] = fl->NIL;
 				fl->curr_frame = fl->SP;
 			}
+			ipd = fl->SP-2;
 			nargs = i+1;
 			NEXT_OP;
 
 		OP(OP_TRYCATCH)
+			fl->Stack[ipd] = (uintptr_t)ip;
 			v = do_trycatch();
 			POPN(1);
 			fl->Stack[fl->SP-1] = v;
@@ -1664,14 +1696,18 @@
 			ip += 4;
 			n = GET_INT32(ip);
 			ip += 4;
-			if(nargs < i)
+			if(__unlikely(nargs < i)){
+				fl->Stack[ipd] = (uintptr_t)ip;
 				lerrorf(fl->ArgError, "too few arguments");
+			}
 			if((int32_t)n > 0){
-				if(nargs > n)
+				if(__unlikely(nargs > n)){
+					fl->Stack[ipd] = (uintptr_t)ip;
 					lerrorf(fl->ArgError, "too many arguments");
+				}
 			}else
 				n = -n;
-			if(n > nargs){
+			if(__likely(n > nargs)){
 				n -= nargs;
 				fl->SP += n;
 				fl->Stack[fl->SP-1] = fl->Stack[fl->SP-n-1];
@@ -1680,6 +1716,7 @@
 				fl->Stack[fl->SP-4] = fl->Stack[fl->SP-n-4];
 				fl->Stack[fl->SP-5] = fl->Stack[fl->SP-n-5];
 				fl->curr_frame = fl->SP;
+				ipd = fl->SP-2;
 				for(i = 0; i < n; i++)
 					fl->Stack[bp+nargs+i] = UNBOUND;
 				nargs += n;
@@ -1702,6 +1739,7 @@
 			ip += 4;
 			s = GET_INT32(ip);
 			ip += 4;
+			fl->Stack[ipd] = (uintptr_t)ip;
 			nargs = process_keys(v, i, n, labs(s)-(i+n), bp, nargs, s<0);
 			NEXT_OP;
 		}
@@ -1754,8 +1792,7 @@
 			memmove(&vector_elt(v, 1),
 				   &vector_elt(fl->Stack[bp+1], 0), (sz-1)*sizeof(value_t));
 		}else{
-			uint32_t i;
-			for(i = 0; i < sz; i++){
+			for(uint32_t i = 0; i < sz; i++){
 				value_t si = fl->Stack[bp+i];
 				// if there's an error evaluating argument defaults some slots
 				// might be left set to UNBOUND (issue #22)
@@ -1785,9 +1822,9 @@
 		return fn_builtin_builtin(args, nargs);
 	if(nargs < 2 || nargs > 4)
 		argcount(nargs, 2);
-	if(!fl_isstring(args[0]))
+	if(__unlikely(!fl_isstring(args[0])))
 		type_error("string", args[0]);
-	if(!isvector(args[1]))
+	if(__unlikely(!isvector(args[1])))
 		type_error("vector", args[1]);
 	cvalue_t *arr = (cvalue_t*)ptr(args[0]);
 	cv_pin(arr);
@@ -1822,12 +1859,12 @@
 		}else{
 			fn->env = args[2];
 			if(nargs > 3){
-				if(!issymbol(args[3]))
+				if(__unlikely(!issymbol(args[3])))
 					type_error("symbol", args[3]);
 				fn->name = args[3];
 			}
 		}
-		if(isgensym(fn->name))
+		if(__unlikely(isgensym(fn->name)))
 			lerrorf(fl->ArgError, "name should not be a gensym");
 	}
 	return fv;
@@ -1837,7 +1874,7 @@
 {
 	argcount(nargs, 1);
 	value_t v = args[0];
-	if(!isclosure(v))
+	if(__unlikely(!isclosure(v)))
 		type_error("function", v);
 	return fn_bcode(v);
 }
@@ -1846,7 +1883,7 @@
 {
 	argcount(nargs, 1);
 	value_t v = args[0];
-	if(!isclosure(v))
+	if(__unlikely(!isclosure(v)))
 		type_error("function", v);
 	return fn_vals(v);
 }
@@ -1855,7 +1892,7 @@
 {
 	argcount(nargs, 1);
 	value_t v = args[0];
-	if(!isclosure(v))
+	if(__unlikely(!isclosure(v)))
 		type_error("function", v);
 	return fn_env(v);
 }
@@ -1864,7 +1901,7 @@
 {
 	argcount(nargs, 1);
 	value_t v = args[0];
-	if(!isclosure(v))
+	if(__unlikely(!isclosure(v)))
 		type_error("function", v);
 	return fn_name(v);
 }
@@ -1918,7 +1955,7 @@
 
 BUILTIN("map", map)
 {
-	if(nargs < 2)
+	if(__unlikely(nargs < 2))
 		lerrorf(fl->ArgError, "too few arguments");
 	if(!iscons(args[1]))
 		return fl->NIL;
--- a/flisp.h
+++ b/flisp.h
@@ -326,7 +326,6 @@
 typedef struct Fl Fl;
 
 struct Fl {
-	const uint8_t *ip;
 	value_t *Stack;
 	uint32_t SP;
 	uint32_t N_STACK;