ref: fdd1fd39e3a616139e48dae992ebc5d5cd710fb7
parent: 377087f52df398745bee200286c38cc0177b1632
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Feb 11 21:40:51 EST 2025
vm: rearrange ops logic from most frequent to least frequent hit Based on coverage reports when running tests.
--- a/src/vm.inc
+++ b/src/vm.inc
@@ -2,24 +2,6 @@
PUSH(FL(stack)[bp]);
NEXT_OP;
-OP(OP_LOADA1)
- PUSH(FL(stack)[bp+1]);
- NEXT_OP;
-
-OP(OP_LOADV)
- v = fn_vals(FL(stack)[bp-1]);
- assert(*ip < vector_size(v));
- PUSH(vector_elt(v, *ip++));
- NEXT_OP;
-
-OP(OP_BRN)
- ip += POP() == FL_nil ? GET_INT16(ip) : 2;
- NEXT_OP;
-
-OP(OP_POP)
- POPN(1);
- NEXT_OP;
-
OP(OP_TCALLL)
tail = true;
if(0){
@@ -63,10 +45,10 @@
FL(stack)[s] = FL(stack)[s+1];
FL(sp)--;
switch(i){
- case OP_LIST: goto LABEL(apply_list);
case OP_VECTOR: goto LABEL(apply_vector);
- case OP_APPLY: goto LABEL(apply_apply);
case OP_ADD: goto LABEL(apply_add);
+ case OP_LIST: goto LABEL(apply_list);
+ case OP_APPLY: goto LABEL(apply_apply);
case OP_SUB: goto LABEL(apply_sub);
case OP_MUL: goto LABEL(apply_mul);
case OP_DIV: goto LABEL(apply_div);
@@ -91,6 +73,51 @@
}
type_error("function", v);
+OP(OP_ARGC)
+ n = *ip++;
+ if(0){
+OP(OP_ARGCL)
+ n = GET_INT32(ip);
+ ip += 4;
+ }
+ if(fl_unlikely(nargs != n)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ arity_error(nargs, n);
+ }
+ NEXT_OP;
+
+OP(OP_LOADA1)
+ PUSH(FL(stack)[bp+1]);
+ NEXT_OP;
+
+OP(OP_RET)
+ v = POP();
+ FL(sp) = FL(curr_frame);
+ FL(curr_frame) = FL(stack)[FL(sp)-3];
+ if(FL(curr_frame) == top_frame)
+ return v;
+ FL(sp) -= 4+nargs;
+ ipd = FL(curr_frame)-1;
+ ip = (uint8_t*)FL(stack)[ipd];
+ nargs = FL(stack)[FL(curr_frame)-2];
+ bp = FL(curr_frame) - 4 - nargs;
+ FL(stack)[FL(sp)-1] = v;
+ NEXT_OP;
+
+OP(OP_LOAD1)
+ PUSH(fixnum(1));
+ NEXT_OP;
+
+OP(OP_LOADA)
+ i = *ip++;
+ v = FL(stack)[bp+i];
+ PUSH(v);
+ NEXT_OP;
+
+OP(OP_BRN)
+ ip += POP() == FL_nil ? GET_INT16(ip) : 2;
+ NEXT_OP;
+
OP(OP_LOADGL)
v = fn_vals(FL(stack)[bp-1]);
v = vector_elt(v, GET_INT32(ip));
@@ -111,54 +138,75 @@
PUSH(sym->binding);
NEXT_OP;
-OP(OP_LOADA)
- i = *ip++;
- v = FL(stack)[bp+i];
- PUSH(v);
+OP(OP_LT)
+ n = *ip++;
+LABEL(apply_lt):
+ {
+ i = n;
+ value_t a = FL(stack)[FL(sp)-i], b;
+ for(v = FL_t; i > 1; a = b){
+ i--;
+ b = FL(stack)[FL(sp)-i];
+ if(bothfixnums(a, b)){
+ if((fixnum_t)a >= (fixnum_t)b){
+ v = FL_nil;
+ break;
+ }
+ }else{
+ x = numeric_compare(a, b, false, false, false);
+ if(x > 1)
+ x = numval(fl_compare(a, b, false));
+ if(x >= 0){
+ v = FL_nil;
+ break;
+ }
+ }
+ }
+ POPN(n);
+ PUSH(v);
+ }
NEXT_OP;
-OP(OP_LOADC)
- i = *ip++;
- v = FL(stack)[bp+nargs];
- assert(isvector(v));
- assert(i < vector_size(v));
- PUSH(vector_elt(v, i));
+OP(OP_LOADV)
+ v = fn_vals(FL(stack)[bp-1]);
+ assert(*ip < vector_size(v));
+ PUSH(vector_elt(v, *ip++));
NEXT_OP;
-OP(OP_BOX)
- i = *ip++;
- v = mk_cons();
- car_(v) = FL(stack)[bp+i];
- cdr_(v) = FL_nil;
- FL(stack)[bp+i] = v;
+OP(OP_ADD2)
+LABEL(do_add2):
+ FL(stack)[ipd] = (uintptr_t)ip;
+ if(0){
+OP(OP_SUB2)
+LABEL(do_sub2):
+ FL(stack)[ipd] = (uintptr_t)ip;
+ FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
+ }
+ {
+ value_t a, b, q;
+ a = FL(stack)[FL(sp)-2];
+ b = FL(stack)[FL(sp)-1];
+ if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &q) && fits_fixnum(q)){
+ v = fixnum(q);
+ }else{
+ v = fl_add_any(&FL(stack)[FL(sp)-2], 2);
+ }
+ }
+ POPN(1);
+ FL(stack)[FL(sp)-1] = v;
NEXT_OP;
-OP(OP_BOXL)
- i = GET_INT32(ip); ip += 4;
- v = mk_cons();
- car_(v) = FL(stack)[bp+i];
- cdr_(v) = FL_nil;
- FL(stack)[bp+i] = v;
+OP(OP_LOADI8)
+ s = (int8_t)*ip++;
+ PUSH(fixnum(s));
NEXT_OP;
-OP(OP_SHIFT)
- i = *ip++;
- FL(stack)[FL(sp)-1-i] = FL(stack)[FL(sp)-1];
- FL(sp) -= i;
+OP(OP_POP)
+ POPN(1);
NEXT_OP;
-OP(OP_RET)
- v = POP();
- FL(sp) = FL(curr_frame);
- FL(curr_frame) = FL(stack)[FL(sp)-3];
- if(FL(curr_frame) == top_frame)
- return v;
- FL(sp) -= 4+nargs;
- ipd = FL(curr_frame)-1;
- ip = (uint8_t*)FL(stack)[ipd];
- nargs = FL(stack)[FL(curr_frame)-2];
- bp = FL(curr_frame) - 4 - nargs;
- FL(stack)[FL(sp)-1] = v;
+OP(OP_BRNN)
+ ip += POP() != FL_nil ? GET_INT16(ip) : 2;
NEXT_OP;
OP(OP_DUP)
@@ -166,6 +214,10 @@
FL(sp)++;
NEXT_OP;
+OP(OP_LOADC0)
+ PUSH(vector_elt(FL(stack)[bp+nargs], 0));
+ NEXT_OP;
+
OP(OP_CAR)
v = FL(stack)[FL(sp)-1];
if(fl_likely(iscons(v)))
@@ -177,17 +229,6 @@
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
-OP(OP_CDR)
- v = FL(stack)[FL(sp)-1];
- if(fl_likely(iscons(v)))
- v = cdr_(v);
- else if(fl_unlikely(v != FL_nil)){
- FL(stack)[ipd] = (uintptr_t)ip;
- type_error("cons", v);
- }
- FL(stack)[FL(sp)-1] = v;
- NEXT_OP;
-
OP(OP_CLOSURE)
n = *ip++;
assert(n > 0);
@@ -215,6 +256,42 @@
FL(stack)[FL(sp)-1] = tagptr(pv, TAG_FUNCTION);
NEXT_OP;
+OP(OP_CONS)
+ if(FL(curheap) > FL(lim))
+ fl_gc(0);
+ c = (cons_t*)FL(curheap);
+ FL(curheap) += sizeof(cons_t);
+ 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;
+
+OP(OP_BRNE)
+ ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT16(ip) : 2;
+ POPN(2);
+ NEXT_OP;
+
+OP(OP_CDR)
+ v = FL(stack)[FL(sp)-1];
+ if(fl_likely(iscons(v)))
+ v = cdr_(v);
+ else if(fl_unlikely(v != FL_nil)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ type_error("cons", v);
+ }
+ FL(stack)[FL(sp)-1] = v;
+ NEXT_OP;
+
+OP(OP_LOADVOID)
+ PUSH(FL_void);
+ NEXT_OP;
+
+OP(OP_NOT)
+ v = FL(stack)[FL(sp)-1];
+ FL(stack)[FL(sp)-1] = v == FL_nil ? FL_t : FL_nil;
+ NEXT_OP;
+
OP(OP_SETA)
v = FL(stack)[FL(sp)-1];
i = *ip++;
@@ -221,39 +298,76 @@
FL(stack)[bp+i] = v;
NEXT_OP;
-OP(OP_JMP)
- ip += GET_INT16(ip);
+OP(OP_VARGC)
+ i = *ip++;
+ if(0){
+OP(OP_VARGCL)
+ i = GET_INT32(ip);
+ ip += 4;
+ }
+ s = (fixnum_t)nargs - (fixnum_t)i;
+ if(s > 0){
+ v = list(&FL(stack)[bp+i], s, 0);
+ FL(stack)[bp+i] = v;
+ if(s > 1){
+ FL(stack)[bp+i+1] = FL(stack)[bp+nargs+0];
+ FL(stack)[bp+i+2] = FL(stack)[bp+nargs+1];
+ FL(stack)[bp+i+3] = i+1;
+ FL(stack)[bp+i+4] = 0;
+ FL(sp) = bp+i+5;
+ FL(curr_frame) = FL(sp);
+ }
+ }else if(fl_unlikely(s < 0)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ lerrorf(FL_ArgError, "too few arguments");
+ }else{
+ FL(sp)++;
+ FL(stack)[FL(sp)-2] = i+1;
+ FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-4];
+ FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-5];
+ FL(stack)[FL(sp)-5] = FL_nil;
+ FL(curr_frame) = FL(sp);
+ }
+ ipd = FL(sp)-1;
+ nargs = i+1;
NEXT_OP;
-OP(OP_LOADC0)
- PUSH(vector_elt(FL(stack)[bp+nargs], 0));
+OP(OP_SHIFT)
+ i = *ip++;
+ FL(stack)[FL(sp)-1-i] = FL(stack)[FL(sp)-1];
+ FL(sp) -= i;
NEXT_OP;
-OP(OP_CONSP)
- FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
+OP(OP_SETCAR)
+ v = FL(stack)[FL(sp)-2];
+ if(fl_unlikely(!iscons(v))){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ type_error("cons", v);
+ }
+ car_(v) = FL(stack)[FL(sp)-1];
+ POPN(1);
NEXT_OP;
-OP(OP_BRNE)
- ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT16(ip) : 2;
- POPN(2);
+OP(OP_LOADNIL)
+ PUSH(FL_nil);
NEXT_OP;
-OP(OP_LOADT)
- PUSH(FL_t);
+OP(OP_BOX)
+ i = *ip++;
+ v = mk_cons();
+ car_(v) = FL(stack)[bp+i];
+ cdr_(v) = FL_nil;
+ FL(stack)[bp+i] = v;
NEXT_OP;
-OP(OP_LOADVOID)
- PUSH(FL_void);
+OP(OP_JMP)
+ ip += GET_INT16(ip);
NEXT_OP;
-OP(OP_LOAD0)
- PUSH(fixnum(0));
+OP(OP_ATOMP)
+ FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_nil : FL_t;
NEXT_OP;
-OP(OP_LOADC1)
- PUSH(vector_elt(FL(stack)[bp+nargs], 1));
- NEXT_OP;
-
OP(OP_AREF2)
n = 2;
if(0){
@@ -293,129 +407,6 @@
PUSH(v);
NEXT_OP;
-OP(OP_ATOMP)
- FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_nil : FL_t;
- NEXT_OP;
-
-OP(OP_BRNN)
- ip += POP() != FL_nil ? GET_INT16(ip) : 2;
- NEXT_OP;
-
-OP(OP_LOAD1)
- PUSH(fixnum(1));
- NEXT_OP;
-
-OP(OP_LT)
- n = *ip++;
-LABEL(apply_lt):
- {
- i = n;
- value_t a = FL(stack)[FL(sp)-i], b;
- for(v = FL_t; i > 1; a = b){
- i--;
- b = FL(stack)[FL(sp)-i];
- if(bothfixnums(a, b)){
- if((fixnum_t)a >= (fixnum_t)b){
- v = FL_nil;
- break;
- }
- }else{
- x = numeric_compare(a, b, false, false, false);
- if(x > 1)
- x = numval(fl_compare(a, b, false));
- if(x >= 0){
- v = FL_nil;
- break;
- }
- }
- }
- POPN(n);
- PUSH(v);
- }
- NEXT_OP;
-
-OP(OP_ADD2)
-LABEL(do_add2):
- FL(stack)[ipd] = (uintptr_t)ip;
- if(0){
-OP(OP_SUB2)
-LABEL(do_sub2):
- FL(stack)[ipd] = (uintptr_t)ip;
- FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
- }
- {
- value_t a, b, q;
- a = FL(stack)[FL(sp)-2];
- b = FL(stack)[FL(sp)-1];
- if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &q) && fits_fixnum(q)){
- v = fixnum(q);
- }else{
- v = fl_add_any(&FL(stack)[FL(sp)-2], 2);
- }
- }
- POPN(1);
- FL(stack)[FL(sp)-1] = v;
- NEXT_OP;
-
-OP(OP_SETCDR)
- v = FL(stack)[FL(sp)-2];
- if(fl_unlikely(!iscons(v))){
- FL(stack)[ipd] = (uintptr_t)ip;
- type_error("cons", v);
- }
- cdr_(v) = FL(stack)[FL(sp)-1];
- POPN(1);
- NEXT_OP;
-
-OP(OP_CONS)
- if(FL(curheap) > FL(lim))
- fl_gc(0);
- c = (cons_t*)FL(curheap);
- FL(curheap) += sizeof(cons_t);
- 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;
-
-OP(OP_EQ)
- FL(stack)[FL(sp)-2] = FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1] ? FL_t : FL_nil;
- POPN(1);
- NEXT_OP;
-
-OP(OP_SYMBOLP)
- FL(stack)[FL(sp)-1] = issymbol(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
- NEXT_OP;
-
-OP(OP_NOT)
- v = FL(stack)[FL(sp)-1];
- FL(stack)[FL(sp)-1] = v == FL_nil ? FL_t : FL_nil;
- NEXT_OP;
-
-OP(OP_CADR)
- v = FL(stack)[FL(sp)-1];
- if(fl_likely(iscons(v))){
- v = cdr_(v);
- if(fl_likely(iscons(v)))
- v = car_(v);
- else
- goto LABEL(cadr_nil);
- }else{
-LABEL(cadr_nil):
- if(fl_unlikely(v != FL_nil)){
- FL(stack)[ipd] = (uintptr_t)ip;
- type_error("cons", v);
- }
- }
- FL(stack)[FL(sp)-1] = v;
- NEXT_OP;
-
-OP(OP_NEG)
-LABEL(do_neg):
- FL(stack)[ipd] = (uintptr_t)ip;
- FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
- NEXT_OP;
-
OP(OP_NANP)
{
value_t q = FL(stack)[FL(sp)-1];
@@ -439,85 +430,157 @@
}
NEXT_OP;
-OP(OP_NUMBERP)
- v = FL(stack)[FL(sp)-1];
- FL(stack)[FL(sp)-1] = fl_isnumber(v) ? FL_t : FL_nil;
+OP(OP_LOAD0)
+ PUSH(fixnum(0));
NEXT_OP;
-OP(OP_FIXNUMP)
- FL(stack)[FL(sp)-1] = isfixnum(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
+OP(OP_SETCDR)
+ v = FL(stack)[FL(sp)-2];
+ if(fl_unlikely(!iscons(v))){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ type_error("cons", v);
+ }
+ cdr_(v) = FL(stack)[FL(sp)-1];
+ POPN(1);
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_nil : FL_t;
+OP(OP_LOADC1)
+ PUSH(vector_elt(FL(stack)[bp+nargs], 1));
NEXT_OP;
-OP(OP_BUILTINP)
- v = FL(stack)[FL(sp)-1];
- FL(stack)[FL(sp)-1] = (isbuiltin(v) || iscbuiltin(v)) ? FL_t : FL_nil;
+OP(OP_ASET)
+ FL(stack)[ipd] = (uintptr_t)ip;
+ v = FL(stack)[FL(sp)-3];
+ n = 3;
+ if(0){
+LABEL(apply_aset):
+ v = FL(stack)[FL(sp)-n];
+ for(i = n-1; i >= 3; i--){
+ if(isarray(v)){
+ FL(stack)[FL(sp)-i-1] = v;
+ v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
+ continue;
+ }
+ e = FL(stack)[FL(sp)-i];
+ isz = tosize(e);
+ if(isvector(v)){
+ if(fl_unlikely(isz >= vector_size(v)))
+ bounds_error(v, e);
+ v = vector_elt(v, isz);
+ continue;
+ }
+ if(!iscons(v) && v != FL_nil)
+ type_error("sequence", v);
+ for(value_t v0 = v;; isz--){
+ if(isz == 0){
+ v = car_(v);
+ break;
+ }
+ v = cdr_(v);
+ if(fl_unlikely(!iscons(v)))
+ bounds_error(v0, e);
+ }
+ }
+ FL(stack)[FL(sp)-3] = v;
+ }
+ e = FL(stack)[FL(sp)-2];
+ isz = tosize(e);
+ if(isvector(v)){
+ if(fl_unlikely(isz >= vector_size(v)))
+ bounds_error(v, e);
+ vector_elt(v, isz) = (e = FL(stack)[FL(sp)-1]);
+ }else if(iscons(v) || v == FL_nil){
+ for(value_t v0 = v;; isz--){
+ if(isz == 0){
+ car_(v) = (e = FL(stack)[FL(sp)-1]);
+ break;
+ }
+ v = cdr_(v);
+ if(fl_unlikely(!iscons(v)))
+ bounds_error(v0, e);
+ }
+ }else if(isarray(v)){
+ e = cvalue_array_aset(&FL(stack)[FL(sp)-3]);
+ }else{
+ type_error("sequence", v);
+ }
+ POPN(n);
+ PUSH(e);
NEXT_OP;
-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_t : FL_nil;
+OP(OP_EQUAL)
+ if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1])
+ v = FL_t;
+ else
+ v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;//FL_nil
+ FL(stack)[FL(sp)-2] = v;
+ POPN(1);
NEXT_OP;
-OP(OP_VECTORP)
- FL(stack)[FL(sp)-1] = isvector(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
+OP(OP_CONSP)
+ FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
-OP(OP_JMPL)
- ip += GET_INT32(ip);
+OP(OP_LOADC)
+ i = *ip++;
+ v = FL(stack)[bp+nargs];
+ assert(isvector(v));
+ assert(i < vector_size(v));
+ PUSH(vector_elt(v, i));
NEXT_OP;
-OP(OP_BRNEL)
- ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT32(ip) : 4;
- POPN(2);
+OP(OP_SYMBOLP)
+ FL(stack)[FL(sp)-1] = issymbol(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
-OP(OP_BRNNL)
- ip += POP() != FL_nil ? GET_INT32(ip) : 4;
+OP(OP_NUMBERP)
+ v = FL(stack)[FL(sp)-1];
+ FL(stack)[FL(sp)-1] = fl_isnumber(v) ? FL_t : FL_nil;
NEXT_OP;
-OP(OP_BRNL)
- ip += POP() == FL_nil ? GET_INT32(ip) : 4;
+OP(OP_BRBOUND)
+ i = GET_INT32(ip);
+ ip += 4;
+ v = FL(stack)[bp+i];
+ PUSH(v != UNBOUND ? FL_t : FL_nil);
NEXT_OP;
-OP(OP_EQV)
- if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1])
- v = FL_t;
- else if(!leafp(FL(stack)[FL(sp)-2]) || !leafp(FL(stack)[FL(sp)-1]))
- v = FL_nil;
- else
- v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;//FL_nil
- FL(stack)[FL(sp)-2] = v;
- POPN(1);
+OP(OP_OPTARGS)
+ i = GET_INT32(ip);
+ ip += 4;
+ n = GET_INT32(ip);
+ ip += 4;
+ if(fl_unlikely(nargs < i)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ lerrorf(FL_ArgError, "too few arguments");
+ }
+ if((int32_t)n > 0){
+ if(fl_unlikely(nargs > n)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ lerrorf(FL_ArgError, "too many arguments");
+ }
+ }else
+ n = -n;
+ if(fl_likely(n > nargs)){
+ n -= nargs;
+ FL(sp) += n;
+ FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-n-1];
+ FL(stack)[FL(sp)-2] = nargs+n;
+ FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-n-3];
+ FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-n-4];
+ FL(curr_frame) = FL(sp);
+ ipd = FL(sp)-1;
+ for(i = 0; i < n; i++)
+ FL(stack)[bp+nargs+i] = UNBOUND;
+ nargs += n;
+ }
NEXT_OP;
-OP(OP_EQUAL)
- if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1])
- v = FL_t;
- else
- v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;//FL_nil
- FL(stack)[FL(sp)-2] = v;
+OP(OP_EQ)
+ FL(stack)[FL(sp)-2] = FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1] ? FL_t : FL_nil;
POPN(1);
NEXT_OP;
-OP(OP_SETCAR)
- v = FL(stack)[FL(sp)-2];
- if(fl_unlikely(!iscons(v))){
- FL(stack)[ipd] = (uintptr_t)ip;
- type_error("cons", v);
- }
- car_(v) = FL(stack)[FL(sp)-1];
- POPN(1);
- NEXT_OP;
-
OP(OP_LIST)
n = *ip++;
LABEL(apply_list):
@@ -530,6 +593,54 @@
}
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_nil : FL_t;
+ NEXT_OP;
+
+OP(OP_NUMEQ)
+ n = *ip++;
+LABEL(apply_numeq):
+ {
+ i = n;
+ value_t a = FL(stack)[FL(sp)-i], b;
+ for(v = FL_t; i > 1; a = b){
+ i--;
+ b = FL(stack)[FL(sp)-i];
+ if(bothfixnums(a, b)){
+ if(a != b){
+ v = FL_nil;
+ break;
+ }
+ }else if(numeric_compare(a, b, true, false, true) != 0){
+ v = FL_nil;
+ break;
+ }
+ }
+ POPN(n);
+ PUSH(v);
+ }
+ NEXT_OP;
+
+OP(OP_CADR)
+ v = FL(stack)[FL(sp)-1];
+ if(fl_likely(iscons(v))){
+ v = cdr_(v);
+ if(fl_likely(iscons(v)))
+ v = car_(v);
+ else
+ goto LABEL(cadr_nil);
+ }else{
+LABEL(cadr_nil):
+ if(fl_unlikely(v != FL_nil)){
+ FL(stack)[ipd] = (uintptr_t)ip;
+ type_error("cons", v);
+ }
+ }
+ FL(stack)[FL(sp)-1] = v;
+ NEXT_OP;
+
OP(OP_TAPPLY)
tail = true;
if(0){
@@ -551,37 +662,25 @@
n = FL(sp)-n;
goto LABEL(do_call);
-OP(OP_ADD)
- n = *ip++;
- if(n == 2)
- goto LABEL(do_add2);
-LABEL(apply_add):
- FL(stack)[ipd] = (uintptr_t)ip;
- v = fl_add_any(&FL(stack)[FL(sp)-n], n);
- POPN(n);
- PUSH(v);
+OP(OP_LOADT)
+ PUSH(FL_t);
NEXT_OP;
-OP(OP_SUB)
- n = *ip++;
-LABEL(apply_sub):
- if(n == 2)
- goto LABEL(do_sub2);
- if(n == 1)
- goto LABEL(do_neg);
+OP(OP_BUILTINP)
+ v = FL(stack)[FL(sp)-1];
+ FL(stack)[FL(sp)-1] = (isbuiltin(v) || iscbuiltin(v)) ? FL_t : FL_nil;
+ NEXT_OP;
+
+OP(OP_NEG)
+LABEL(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
- PUSH(FL(stack)[i]);
- FL(stack)[i] = fixnum(0);
- FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n));
- FL(stack)[i] = POP();
- v = fl_add_any(&FL(stack)[i], 2);
- POPN(n);
- PUSH(v);
+ FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
NEXT_OP;
+OP(OP_FIXNUMP)
+ FL(stack)[FL(sp)-1] = isfixnum(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
+ NEXT_OP;
+
OP(OP_MUL)
n = *ip++;
LABEL(apply_mul):
@@ -591,26 +690,6 @@
PUSH(v);
NEXT_OP;
-OP(OP_DIV)
- n = *ip++;
-LABEL(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]);
- }else{
- if(n > 2){
- PUSH(FL(stack)[i]);
- FL(stack)[i] = fixnum(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]);
- POPN(n);
- PUSH(v);
- }
- NEXT_OP;
-
OP(OP_IDIV)
{
value_t a = FL(stack)[FL(sp)-2];
@@ -630,48 +709,26 @@
}
NEXT_OP;
-OP(OP_NUMEQ)
+OP(OP_DIV)
n = *ip++;
-LABEL(apply_numeq):
- {
- i = n;
- value_t a = FL(stack)[FL(sp)-i], b;
- for(v = FL_t; i > 1; a = b){
- i--;
- b = FL(stack)[FL(sp)-i];
- if(bothfixnums(a, b)){
- if(a != b){
- v = FL_nil;
- break;
- }
- }else if(numeric_compare(a, b, true, false, true) != 0){
- v = FL_nil;
- break;
- }
+LABEL(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]);
+ }else{
+ if(n > 2){
+ PUSH(FL(stack)[i]);
+ FL(stack)[i] = fixnum(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]);
POPN(n);
PUSH(v);
}
NEXT_OP;
-OP(OP_COMPARE)
- FL(stack)[FL(sp)-2] = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], false);
- POPN(1);
- NEXT_OP;
-
-OP(OP_ARGC)
- n = *ip++;
- if(0){
-OP(OP_ARGCL)
- n = GET_INT32(ip);
- ip += 4;
- }
- if(fl_unlikely(nargs != n)){
- FL(stack)[ipd] = (uintptr_t)ip;
- arity_error(nargs, n);
- }
- NEXT_OP;
-
OP(OP_VECTOR)
n = *ip++;
LABEL(apply_vector):
@@ -683,64 +740,9 @@
PUSH(v);
NEXT_OP;
-OP(OP_ASET)
- FL(stack)[ipd] = (uintptr_t)ip;
- v = FL(stack)[FL(sp)-3];
- n = 3;
- if(0){
-LABEL(apply_aset):
- v = FL(stack)[FL(sp)-n];
- for(i = n-1; i >= 3; i--){
- if(isarray(v)){
- FL(stack)[FL(sp)-i-1] = v;
- v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]);
- continue;
- }
- e = FL(stack)[FL(sp)-i];
- isz = tosize(e);
- if(isvector(v)){
- if(fl_unlikely(isz >= vector_size(v)))
- bounds_error(v, e);
- v = vector_elt(v, isz);
- continue;
- }
- if(!iscons(v) && v != FL_nil)
- type_error("sequence", v);
- for(value_t v0 = v;; isz--){
- if(isz == 0){
- v = car_(v);
- break;
- }
- v = cdr_(v);
- if(fl_unlikely(!iscons(v)))
- bounds_error(v0, e);
- }
- }
- FL(stack)[FL(sp)-3] = v;
- }
- e = FL(stack)[FL(sp)-2];
- isz = tosize(e);
- if(isvector(v)){
- if(fl_unlikely(isz >= vector_size(v)))
- bounds_error(v, e);
- vector_elt(v, isz) = (e = FL(stack)[FL(sp)-1]);
- }else if(iscons(v) || v == FL_nil){
- for(value_t v0 = v;; isz--){
- if(isz == 0){
- car_(v) = (e = FL(stack)[FL(sp)-1]);
- break;
- }
- v = cdr_(v);
- if(fl_unlikely(!iscons(v)))
- bounds_error(v0, e);
- }
- }else if(isarray(v)){
- e = cvalue_array_aset(&FL(stack)[FL(sp)-3]);
- }else{
- type_error("sequence", v);
- }
- POPN(n);
- PUSH(e);
+OP(OP_COMPARE)
+ FL(stack)[FL(sp)-2] = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], false);
+ POPN(1);
NEXT_OP;
OP(OP_FOR)
@@ -760,22 +762,6 @@
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
-OP(OP_LOADNIL)
- PUSH(FL_nil);
- NEXT_OP;
-
-OP(OP_LOADI8)
- s = (int8_t)*ip++;
- PUSH(fixnum(s));
- NEXT_OP;
-
-OP(OP_LOADVL)
- v = fn_vals(FL(stack)[bp-1]);
- v = vector_elt(v, GET_INT32(ip));
- ip += 4;
- PUSH(v);
- NEXT_OP;
-
OP(OP_SETGL)
v = fn_vals(FL(stack)[bp-1]);
v = vector_elt(v, GET_INT32(ip));
@@ -794,6 +780,28 @@
sym->binding = v;
NEXT_OP;
+OP(OP_VECTORP)
+ FL(stack)[FL(sp)-1] = isvector(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
+ NEXT_OP;
+
+OP(OP_TRYCATCH)
+ FL(stack)[ipd] = (uintptr_t)ip;
+ v = do_trycatch();
+ POPN(1);
+ FL(stack)[FL(sp)-1] = v;
+ NEXT_OP;
+
+OP(OP_ADD)
+ n = *ip++;
+ if(n == 2)
+ goto LABEL(do_add2);
+LABEL(apply_add):
+ FL(stack)[ipd] = (uintptr_t)ip;
+ v = fl_add_any(&FL(stack)[FL(sp)-n], n);
+ POPN(n);
+ PUSH(v);
+ NEXT_OP;
+
OP(OP_LOADAL)
assert(nargs > 0);
i = GET_INT32(ip);
@@ -802,6 +810,55 @@
PUSH(v);
NEXT_OP;
+OP(OP_EQV)
+ if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1])
+ v = FL_t;
+ else if(!leafp(FL(stack)[FL(sp)-2]) || !leafp(FL(stack)[FL(sp)-1]))
+ v = FL_nil;
+ else
+ v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;//FL_nil
+ FL(stack)[FL(sp)-2] = v;
+ POPN(1);
+ NEXT_OP;
+
+OP(OP_KEYARGS)
+ v = fn_vals(FL(stack)[bp-1]);
+ v = vector_elt(v, 0);
+ i = GET_INT32(ip);
+ ip += 4;
+ n = GET_INT32(ip);
+ 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);
+ ipd = FL(sp)-1;
+ NEXT_OP;
+
+OP(OP_SUB)
+ n = *ip++;
+LABEL(apply_sub):
+ if(n == 2)
+ goto LABEL(do_sub2);
+ if(n == 1)
+ goto LABEL(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
+ PUSH(FL(stack)[i]);
+ FL(stack)[i] = fixnum(0);
+ FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n));
+ FL(stack)[i] = POP();
+ v = fl_add_any(&FL(stack)[i], 2);
+ POPN(n);
+ PUSH(v);
+ NEXT_OP;
+
+OP(OP_BRNL)
+ ip += POP() == FL_nil ? GET_INT32(ip) : 4;
+ NEXT_OP;
+
OP(OP_SETAL)
v = FL(stack)[FL(sp)-1];
i = GET_INT32(ip);
@@ -809,102 +866,45 @@
FL(stack)[bp+i] = v;
NEXT_OP;
-OP(OP_LOADCL)
- i = GET_INT32(ip);
- ip += 4;
- v = FL(stack)[bp+nargs];
- PUSH(vector_elt(v, i));
+OP(OP_BOXL)
+ i = GET_INT32(ip); ip += 4;
+ v = mk_cons();
+ car_(v) = FL(stack)[bp+i];
+ cdr_(v) = FL_nil;
+ FL(stack)[bp+i] = v;
NEXT_OP;
-OP(OP_VARGC)
- i = *ip++;
- if(0){
-OP(OP_VARGCL)
- i = GET_INT32(ip);
- ip += 4;
- }
- s = (fixnum_t)nargs - (fixnum_t)i;
- if(s > 0){
- v = list(&FL(stack)[bp+i], s, 0);
- FL(stack)[bp+i] = v;
- if(s > 1){
- FL(stack)[bp+i+1] = FL(stack)[bp+nargs+0];
- FL(stack)[bp+i+2] = FL(stack)[bp+nargs+1];
- FL(stack)[bp+i+3] = i+1;
- FL(stack)[bp+i+4] = 0;
- FL(sp) = bp+i+5;
- FL(curr_frame) = FL(sp);
- }
- }else if(fl_unlikely(s < 0)){
- FL(stack)[ipd] = (uintptr_t)ip;
- lerrorf(FL_ArgError, "too few arguments");
- }else{
- FL(sp)++;
- FL(stack)[FL(sp)-2] = i+1;
- FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-4];
- FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-5];
- FL(stack)[FL(sp)-5] = FL_nil;
- FL(curr_frame) = FL(sp);
- }
- ipd = FL(sp)-1;
- nargs = i+1;
+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_t : FL_nil;
NEXT_OP;
-OP(OP_TRYCATCH)
- FL(stack)[ipd] = (uintptr_t)ip;
- v = do_trycatch();
- POPN(1);
- FL(stack)[FL(sp)-1] = v;
+OP(OP_JMPL)
+ ip += GET_INT32(ip);
NEXT_OP;
-OP(OP_OPTARGS)
- i = GET_INT32(ip);
- ip += 4;
- n = GET_INT32(ip);
- ip += 4;
- if(fl_unlikely(nargs < i)){
- FL(stack)[ipd] = (uintptr_t)ip;
- lerrorf(FL_ArgError, "too few arguments");
- }
- if((int32_t)n > 0){
- if(fl_unlikely(nargs > n)){
- FL(stack)[ipd] = (uintptr_t)ip;
- lerrorf(FL_ArgError, "too many arguments");
- }
- }else
- n = -n;
- if(fl_likely(n > nargs)){
- n -= nargs;
- FL(sp) += n;
- FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-n-1];
- FL(stack)[FL(sp)-2] = nargs+n;
- FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-n-3];
- FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-n-4];
- FL(curr_frame) = FL(sp);
- ipd = FL(sp)-1;
- for(i = 0; i < n; i++)
- FL(stack)[bp+nargs+i] = UNBOUND;
- nargs += n;
- }
+OP(OP_BRNEL)
+ ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT32(ip) : 4;
+ POPN(2);
NEXT_OP;
-OP(OP_BRBOUND)
+OP(OP_BRNNL)
+ ip += POP() != FL_nil ? GET_INT32(ip) : 4;
+ NEXT_OP;
+
+OP(OP_LOADCL)
i = GET_INT32(ip);
ip += 4;
- v = FL(stack)[bp+i];
- PUSH(v != UNBOUND ? FL_t : FL_nil);
+ v = FL(stack)[bp+nargs];
+ PUSH(vector_elt(v, i));
NEXT_OP;
-OP(OP_KEYARGS)
+OP(OP_LOADVL)
v = fn_vals(FL(stack)[bp-1]);
- v = vector_elt(v, 0);
- i = GET_INT32(ip);
+ v = vector_elt(v, GET_INT32(ip));
ip += 4;
- n = GET_INT32(ip);
- 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);
- ipd = FL(sp)-1;
+ PUSH(v);
NEXT_OP;