fixing a case where tail position was not properly observed
This commit is contained in:
		
							parent
							
								
									57c066fcdf
								
							
						
					
					
						commit
						0278b152b8
					
				| 
						 | 
				
			
			@ -808,11 +808,9 @@ static value_t do_trycatch()
 | 
			
		|||
#ifdef USE_COMPUTED_GOTO
 | 
			
		||||
#define OP(x) L_##x:
 | 
			
		||||
#define NEXT_OP goto *vm_labels[*ip++]
 | 
			
		||||
#define DISPATCH goto *vm_labels[op]
 | 
			
		||||
#else
 | 
			
		||||
#define OP(x) case x:
 | 
			
		||||
#define NEXT_OP goto next_op
 | 
			
		||||
#define DISPATCH goto dispatch
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -831,6 +829,7 @@ static value_t do_trycatch()
 | 
			
		|||
static value_t apply_cl(uint32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    VM_LABELS;
 | 
			
		||||
    VM_APPLY_LABELS;
 | 
			
		||||
    uint32_t top_frame = curr_frame;
 | 
			
		||||
    // frame variables
 | 
			
		||||
    uint32_t n, captured;
 | 
			
		||||
| 
						 | 
				
			
			@ -839,7 +838,9 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
    fixnum_t s, hi;
 | 
			
		||||
 | 
			
		||||
    // temporary variables (not necessary to preserve across calls)
 | 
			
		||||
#ifndef USE_COMPUTED_GOTO
 | 
			
		||||
    uint32_t op;
 | 
			
		||||
#endif
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    symbol_t *sym;
 | 
			
		||||
    static cons_t *c;
 | 
			
		||||
| 
						 | 
				
			
			@ -877,6 +878,7 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
#endif
 | 
			
		||||
        OP(OP_ARGC)
 | 
			
		||||
            n = *ip++;
 | 
			
		||||
        do_argc:
 | 
			
		||||
            if (nargs != n) {
 | 
			
		||||
                if (nargs > n)
 | 
			
		||||
                    lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
| 
						 | 
				
			
			@ -916,13 +918,7 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
            NEXT_OP;
 | 
			
		||||
        OP(OP_LARGC)
 | 
			
		||||
            n = GET_INT32(ip); ip+=4;
 | 
			
		||||
            if (nargs != n) {
 | 
			
		||||
                if (nargs > n)
 | 
			
		||||
                    lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
                else
 | 
			
		||||
                    lerror(ArgError, "apply: too few arguments");
 | 
			
		||||
            }
 | 
			
		||||
            NEXT_OP;
 | 
			
		||||
            goto do_argc;
 | 
			
		||||
        OP(OP_LVARGC)
 | 
			
		||||
            i = GET_INT32(ip); ip+=4;
 | 
			
		||||
            goto do_vargc;
 | 
			
		||||
| 
						 | 
				
			
			@ -941,7 +937,9 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
        OP(OP_TCALL)
 | 
			
		||||
            n = *ip++;  // nargs
 | 
			
		||||
        do_tcall:
 | 
			
		||||
            if (isfunction(Stack[SP-n-1])) {
 | 
			
		||||
            func = Stack[SP-n-1];
 | 
			
		||||
            if (tag(func) == TAG_FUNCTION) {
 | 
			
		||||
                if (func > (N_BUILTINS<<3)) {
 | 
			
		||||
                    curr_frame = Stack[curr_frame-4];
 | 
			
		||||
                    for(s=-1; s < (fixnum_t)n; s++)
 | 
			
		||||
                        Stack[bp+s] = Stack[SP-n+s];
 | 
			
		||||
| 
						 | 
				
			
			@ -949,12 +947,52 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
                    nargs = n;
 | 
			
		||||
                    goto apply_cl_top;
 | 
			
		||||
                }
 | 
			
		||||
            goto do_call;
 | 
			
		||||
                else {
 | 
			
		||||
                    i = uintval(func);
 | 
			
		||||
                    if (i <= OP_ASET) {
 | 
			
		||||
                        s = builtin_arg_counts[i];
 | 
			
		||||
                        if (s >= 0)
 | 
			
		||||
                            argcount(builtin_names[i], n, s);
 | 
			
		||||
                        else if (s != ANYARGS && (signed)n < -s)
 | 
			
		||||
                            argcount(builtin_names[i], n, -s);
 | 
			
		||||
                        // remove function arg
 | 
			
		||||
                        for(s=SP-n-1; s < (int)SP-1; s++)
 | 
			
		||||
                            Stack[s] = Stack[s+1];
 | 
			
		||||
                        SP--;
 | 
			
		||||
#ifdef USE_COMPUTED_GOTO
 | 
			
		||||
                        if (i == OP_APPLY)
 | 
			
		||||
                            goto apply_tapply;
 | 
			
		||||
                        goto *vm_apply_labels[i];
 | 
			
		||||
#else
 | 
			
		||||
                        switch (i) {
 | 
			
		||||
                        case OP_LIST:   goto apply_list;
 | 
			
		||||
                        case OP_VECTOR: goto apply_vector;
 | 
			
		||||
                        case OP_APPLY:  goto apply_tapply;
 | 
			
		||||
                        case OP_ADD:    goto apply_add;
 | 
			
		||||
                        case OP_SUB:    goto apply_sub;
 | 
			
		||||
                        case OP_MUL:    goto apply_mul;
 | 
			
		||||
                        case OP_DIV:    goto apply_div;
 | 
			
		||||
                        default:
 | 
			
		||||
                            op = (uint8_t)i;
 | 
			
		||||
                            goto dispatch;
 | 
			
		||||
                        }
 | 
			
		||||
#endif
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (iscbuiltin(func)) {
 | 
			
		||||
                s = SP;
 | 
			
		||||
                v = (((builtin_t*)ptr(func))[3])(&Stack[SP-n], n);
 | 
			
		||||
                SP = s-n;
 | 
			
		||||
                Stack[SP-1] = v;
 | 
			
		||||
                NEXT_OP;
 | 
			
		||||
            }
 | 
			
		||||
            type_error("apply", "function", func);
 | 
			
		||||
        // WARNING: repeated code ahead
 | 
			
		||||
        OP(OP_CALL)
 | 
			
		||||
            n = *ip++;  // nargs
 | 
			
		||||
        do_call:
 | 
			
		||||
            func = Stack[SP-n-1];
 | 
			
		||||
            s = SP;
 | 
			
		||||
            if (tag(func) == TAG_FUNCTION) {
 | 
			
		||||
                if (func > (N_BUILTINS<<3)) {
 | 
			
		||||
                    Stack[curr_frame-2] = (uptrint_t)ip;
 | 
			
		||||
| 
						 | 
				
			
			@ -963,19 +1001,20 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    i = uintval(func);
 | 
			
		||||
                    if (i > OP_ASET)
 | 
			
		||||
                        type_error("apply", "function", func);
 | 
			
		||||
                    op = (uint8_t)i;
 | 
			
		||||
                    s = builtin_arg_counts[op];
 | 
			
		||||
                    if (i <= OP_ASET) {
 | 
			
		||||
                        s = builtin_arg_counts[i];
 | 
			
		||||
                        if (s >= 0)
 | 
			
		||||
                        argcount(builtin_names[op], n, s);
 | 
			
		||||
                            argcount(builtin_names[i], n, s);
 | 
			
		||||
                        else if (s != ANYARGS && (signed)n < -s)
 | 
			
		||||
                        argcount(builtin_names[op], n, -s);
 | 
			
		||||
                            argcount(builtin_names[i], n, -s);
 | 
			
		||||
                        // remove function arg
 | 
			
		||||
                        for(s=SP-n-1; s < (int)SP-1; s++)
 | 
			
		||||
                            Stack[s] = Stack[s+1];
 | 
			
		||||
                        SP--;
 | 
			
		||||
                    switch (op) {
 | 
			
		||||
#ifdef USE_COMPUTED_GOTO
 | 
			
		||||
                        goto *vm_apply_labels[i];
 | 
			
		||||
#else
 | 
			
		||||
                        switch (i) {
 | 
			
		||||
                        case OP_LIST:   goto apply_list;
 | 
			
		||||
                        case OP_VECTOR: goto apply_vector;
 | 
			
		||||
                        case OP_APPLY:  goto apply_apply;
 | 
			
		||||
| 
						 | 
				
			
			@ -984,19 +1023,21 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
                        case OP_MUL:    goto apply_mul;
 | 
			
		||||
                        case OP_DIV:    goto apply_div;
 | 
			
		||||
                        default:
 | 
			
		||||
                        DISPATCH;
 | 
			
		||||
                            op = (uint8_t)i;
 | 
			
		||||
                            goto dispatch;
 | 
			
		||||
                        }
 | 
			
		||||
#endif
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (iscbuiltin(func)) {
 | 
			
		||||
                s = SP;
 | 
			
		||||
                v = (((builtin_t*)ptr(func))[3])(&Stack[SP-n], n);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                type_error("apply", "function", func);
 | 
			
		||||
            }
 | 
			
		||||
                SP = s-n;
 | 
			
		||||
                Stack[SP-1] = v;
 | 
			
		||||
                NEXT_OP;
 | 
			
		||||
            }
 | 
			
		||||
            type_error("apply", "function", func);
 | 
			
		||||
        OP(OP_JMP) ip += (ptrint_t)GET_INT16(ip); NEXT_OP;
 | 
			
		||||
        OP(OP_BRF)
 | 
			
		||||
            v = POP();
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,10 +1170,19 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
            NEXT_OP;
 | 
			
		||||
 | 
			
		||||
        OP(OP_TAPPLY)
 | 
			
		||||
            n = *ip++;
 | 
			
		||||
        apply_tapply:
 | 
			
		||||
            v = POP();     // arglist
 | 
			
		||||
            n = SP-(n-2);  // n-2 == # leading arguments not in the list
 | 
			
		||||
            while (iscons(v)) {
 | 
			
		||||
                if (SP >= N_STACK)
 | 
			
		||||
                    grow_stack();
 | 
			
		||||
                PUSH(car_(v));
 | 
			
		||||
                v = cdr_(v);
 | 
			
		||||
            }
 | 
			
		||||
            n = SP-n;
 | 
			
		||||
            goto do_tcall;
 | 
			
		||||
        OP(OP_APPLY)
 | 
			
		||||
#ifdef USE_COMPUTED_GOTO
 | 
			
		||||
            op = ip[-1];
 | 
			
		||||
#endif
 | 
			
		||||
            n = *ip++;
 | 
			
		||||
        apply_apply:
 | 
			
		||||
            v = POP();     // arglist
 | 
			
		||||
| 
						 | 
				
			
			@ -1144,8 +1194,7 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
                v = cdr_(v);
 | 
			
		||||
            }
 | 
			
		||||
            n = SP-n;
 | 
			
		||||
            if (op==OP_TAPPLY) goto do_tcall;
 | 
			
		||||
            else goto do_call;
 | 
			
		||||
            goto do_call;
 | 
			
		||||
 | 
			
		||||
        OP(OP_ADD)
 | 
			
		||||
            n = *ip++;
 | 
			
		||||
| 
						 | 
				
			
			@ -1594,12 +1643,10 @@ static uint32_t compute_maxstack(uint8_t *code, size_t len)
 | 
			
		|||
            break;
 | 
			
		||||
        case OP_LARGC:
 | 
			
		||||
            n = GET_INT32(ip); ip+=4;
 | 
			
		||||
            sp += (n+2);
 | 
			
		||||
            break;
 | 
			
		||||
        case OP_LVARGC:
 | 
			
		||||
            // move extra arguments from list to stack
 | 
			
		||||
            n = GET_INT32(ip); ip+=4;
 | 
			
		||||
            sp += (n+3);
 | 
			
		||||
            sp += (n+2);
 | 
			
		||||
            break;
 | 
			
		||||
        case OP_LET: break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,8 +68,30 @@ enum {
 | 
			
		|||
    &&L_OP_LVARGC,                                                      \
 | 
			
		||||
    &&L_OP_LOADA0, &&L_OP_LOADA1, &&L_OP_LOADC00, &&L_OP_LOADC01        \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define VM_APPLY_LABELS                                                 \
 | 
			
		||||
    static void *vm_apply_labels[] = {                                  \
 | 
			
		||||
&&L_OP_NOP, &&L_OP_DUP, &&L_OP_POP, &&L_OP_CALL, &&L_OP_TCALL, &&L_OP_JMP, \
 | 
			
		||||
    &&L_OP_BRF, &&L_OP_BRT,                                             \
 | 
			
		||||
    &&L_OP_JMPL, &&L_OP_BRFL, &&L_OP_BRTL, &&L_OP_RET,                  \
 | 
			
		||||
                                                                        \
 | 
			
		||||
    &&L_OP_EQ, &&L_OP_EQV, &&L_OP_EQUAL, &&L_OP_ATOMP, &&L_OP_NOT,      \
 | 
			
		||||
    &&L_OP_NULLP, &&L_OP_BOOLEANP,                                      \
 | 
			
		||||
    &&L_OP_SYMBOLP, &&L_OP_NUMBERP, &&L_OP_BOUNDP, &&L_OP_PAIRP,        \
 | 
			
		||||
    &&L_OP_BUILTINP, &&L_OP_VECTORP,                                    \
 | 
			
		||||
    &&L_OP_FIXNUMP, &&L_OP_FUNCTIONP,                                   \
 | 
			
		||||
                                                                        \
 | 
			
		||||
    &&L_OP_CONS, &&apply_list, &&L_OP_CAR, &&L_OP_CDR, &&L_OP_SETCAR,    \
 | 
			
		||||
    &&L_OP_SETCDR, &&apply_apply,                                        \
 | 
			
		||||
                                                                        \
 | 
			
		||||
    &&apply_add, &&apply_sub, &&apply_mul, &&apply_div, &&L_OP_IDIV, &&L_OP_NUMEQ, \
 | 
			
		||||
    &&L_OP_LT, &&L_OP_COMPARE,                                          \
 | 
			
		||||
                                                                        \
 | 
			
		||||
    &&apply_vector, &&L_OP_AREF, &&L_OP_ASET                            \
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
#define VM_LABELS
 | 
			
		||||
#define VM_APPLY_LABELS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1040,7 +1040,6 @@ new evaluator todo:
 | 
			
		|||
  . largs instruction to move args after MAX_ARGS from list to stack
 | 
			
		||||
* maxstack calculation, make Stack growable
 | 
			
		||||
  * stack traces and better debugging support
 | 
			
		||||
  - make maxstack calculation robust against invalid bytecode
 | 
			
		||||
* improve internal define
 | 
			
		||||
* try removing MAX_ARGS trickery
 | 
			
		||||
- apply optimization, avoid redundant list copying calling vararg fns
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue