ref: 082a4ea49e1ea955f756bba1d0f8a1b819dcf4b9
dir: /maxstack.inc/
static int
compute_maxstack(uint8_t *code, size_t len)
{
uint8_t *ip = code+4, *end = code+len;
int i, n, sp = 0, maxsp = 0;
while(ip < end){
opcode_t op = *ip++;
if(op >= N_OPCODES)
return -1;
switch(op){
case OP_LOADA: case OP_LOADI8: case OP_LOADV: case OP_LOADG:
ip++; // fallthrough
case OP_LOADA0: case OP_LOADA1:
case OP_DUP: case OP_LOADT: case OP_LOADF: case OP_LOADNIL: case OP_LOADVOID:
case OP_LOAD0:
case OP_LOAD1: case OP_LOADC0:
case OP_LOADC1:
sp++;
break;
case OP_BRF: case OP_BRT:
SWAP_INT16(ip);
ip += 2;
sp--;
break;
case OP_POP: case OP_RET:
case OP_CONS: case OP_SETCAR: case OP_SETCDR:
case OP_EQ: case OP_EQV: case OP_EQUAL: case OP_ADD2: case OP_SUB2:
case OP_IDIV: case OP_COMPARE:
case OP_AREF2: case OP_TRYCATCH:
sp--;
break;
case OP_AREF:
n = 2 + *ip++;
sp -= n;
break;
case OP_ARGC: case OP_SETG: case OP_SETA: case OP_BOX:
ip++;
continue;
case OP_TCALL: case OP_CALL: case OP_CLOSURE: case OP_SHIFT:
n = *ip++; // nargs
sp -= n;
break;
case OP_LOADVL: case OP_LOADGL: case OP_LOADAL:
sp++; // fallthrough
case OP_SETGL: case OP_SETAL: case OP_LARGC: case OP_BOXL:
SWAP_INT32(ip);
ip += 4;
break;
case OP_LOADC:
sp++;
ip++;
break;
case OP_VARGC:
n = *ip++;
sp += n+2;
break;
case OP_LVARGC:
SWAP_INT32(ip);
n = GET_INT32(ip); ip += 4;
sp += n+2;
break;
case OP_OPTARGS:
SWAP_INT32(ip);
i = GET_INT32(ip); ip += 4;
SWAP_INT32(ip);
n = abs(GET_INT32(ip)); ip += 4;
sp += n-i;
break;
case OP_KEYARGS:
SWAP_INT32(ip);
i = GET_INT32(ip); ip += 4;
SWAP_INT32(ip);
ip += 4;
SWAP_INT32(ip);
n = abs(GET_INT32(ip)); ip += 4;
sp += n-i;
break;
case OP_BRBOUND:
SWAP_INT32(ip);
ip += 4;
sp++;
break;
case OP_TCALLL: case OP_CALLL:
SWAP_INT32(ip);
n = GET_INT32(ip); ip+=4;
sp -= n;
break;
case OP_JMP:
SWAP_INT16(ip);
ip += 2;
continue;
case OP_JMPL:
SWAP_INT32(ip);
ip += 4;
continue;
case OP_BRFL: case OP_BRTL:
SWAP_INT32(ip);
ip += 4;
sp--;
break;
case OP_BRNE:
SWAP_INT16(ip);
ip += 2;
sp -= 2;
break;
case OP_BRNEL:
SWAP_INT32(ip);
ip += 4;
sp -= 2;
break;
case OP_BRNN: case OP_BRN:
SWAP_INT16(ip);
ip += 2;
sp--;
break;
case OP_BRNNL: case OP_BRNL:
SWAP_INT32(ip);
ip += 4; // fallthrough
case OP_TAPPLY: case OP_APPLY:
case OP_LIST: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
case OP_VECTOR: case OP_LT: case OP_NUMEQ:
n = *ip++;
sp -= n-1;
break;
case OP_FOR:
if(maxsp < sp+2)
maxsp = sp+2; // fallthrough
case OP_ASET:
sp -= 2;
break;
case OP_LOADCL:
sp++; // fallthrough
SWAP_INT32(ip);
ip += 4;
break;
case OP_CAR: case OP_CDR: case OP_CADR:
case OP_NOT: case OP_NEG:
case OP_CONSP: case OP_ATOMP: case OP_SYMBOLP:
case OP_NULLP: case OP_BOOLEANP: case OP_NUMBERP:
case OP_FIXNUMP: case OP_BOUNDP: case OP_BUILTINP:
case OP_FUNCTIONP: case OP_VECTORP: case OP_NANP:
continue;
case OP_EOF_OBJECT: case N_OPCODES:
return -1;
}
if((int32_t)sp > (int32_t)maxsp)
maxsp = sp;
}
assert(ip == end);
assert(maxsp >= 0);
return maxsp+4;
}