On Fri, 12 Oct 2001, Ritz Daniel wrote: > > >i fixed that. but ther's only a jump_i, no jump_ic... > > > > > >"jump Ix" now jumps to the absolute address held in a register Ix. > > >Absolute means > > >start of the bytecode + Ix. > > > > It can't mean that. This: > > > > set I0, 0 > > jump I0 > > > > should coredump. > > > > i think parrot is a virtual cpu so the word absolute should be seen in context > of the vm, not the real cpu we are running on. > within the vm address 0 should be address 0 of the bytecode, not the > real cpu. but it would be nice to have a null pointer....so what about the first > instruction in bytecode is at vm address 1? so a > set I0, 1 > jump I0 > would be a program restart and 0 is the null pointer for which we can check > with a conditional branch...and a jump to address 0 results in a crash > (it does so on my windoze). > > but the best solution in my opinion would be: > first instruction in bytecode is a 'end' (at address 0), then the program itself > starts at address 1. a jump to address 1 is a program restart, we can check > for null pointer with conditional branch and a jump to address 0 would be an > immediate program end (it doesn't look nice if an interpreter core dumps). or > better than an 'end' is an opcode that throws some error messages, ends the > program but does not core dump.....
I started out with an annoying question, but then managed to answer it myself. Still I think I can clear up some confusion as to the practicals. What you are suggesting basically is: unsigned int PC = interp->pc; int* code = interp->cur_code_segment; optable_t* optable = interp->optable; while(code[PC]) { PC = optable[code[PC]]->(code, PC, interp ) } A bounded version of the op-loop would simply be: while(PC < max_code_size && code[PC] ) DO_OP.. Since we're zero-bounded (due to unsigned int) This requires an extra level of indirection in most op-codes as well as in the main loop (not to mention the marginal overhead of an extra parameter). The assembler would have to do: s/ P(\d) / code[PC + $1] /x; instead of just s/ P(\d) / code[ $1 ] /x; I'm of the opinion that you shouldn't just be able to jump into another code-segment. That the interpreter core should be manipulated (to change the context, such as bounds). In either code[PC] or *code, the jump is still: AUTO_OP jump_i { return(INT_REG(P1)); } And thus be prevented from changing context; That would be relegated to a subroutine invocation (especially since such subroutines can be dynamically modified). I'll have to see some real subroutine implementatinos before I can support this method though. I'm curious to see if gcc -O2 can alleviate the over-head of *(code + PC + offset) for the parameters. For constant offsets, the x86 does a good job (at least at the assembly level; I know that the micro-ops still requires an extra add, but they may just be using a 3-way-add). In any case, I think we're all in agreement about not remapping the physical C-addresses, but for completeness I'll give the reasoning. Given that modulaA will have interp->code range from say 28M to 28.4M, moduleB will have interp->code range from 41.4M to 42.2M, etc - Where-ever mmap assigns the address. It would therefore be almost impossible to map PC to a linear physical address. Obviously PC can't be a contiguous zero-based address, since it's not code[PC], it's PC = cur_code + rel_branch, DO_OP( PC ). Physical indexed jumps, therefore are meaningless. "jump 500" where 500 is a compile-time-constant is really trying to say jump interp->code_base[ 500 ], not PC=500, DO_OP( PC ), since that would be a core-dump (this is c-memory address 500, which is off limits). But "jump interp->code_base[ 500 ]" is physically no more benificial than "branch PC - label"; Jump-register can be useful for certain optimizations (i.e. switch). Note that my original take was that we should either have while(code) DO_OP or while(code && *code) DO_OP as the fast-do-loop, since: set I1, 0 jump I1 would just act like exit. Then I thought about: set I1, 1 jump I1 Which would most definately core-dump. Thus we're not really much safter checking code's address than any other special value. The benifits of while(code[PC]) are potentially outweighed by the overhead of code[PC + arg_offset]. Thus I'm mostly inclined to always support the current "safe" method ("while(code>start && code<stop...") except when a perl6 -O2 is utilized. > > > -daniel > > > >the following code will result in a simple program restart, > > >no core dump: > > > set I1, 0 > > > jump I1 > > > > > >the fixed jump breaks the tests: basic5, call.pasm, jump.pasm > > >but i wonder why nobody realized that jump's broken, the doc says it jumps > > >_to_ > > >the address, not forward or backward........ > > > > That was brought up a while ago, but I don't think anyone's had time to put > > a patch in. I'm working on stack and jsr support, so I'll fix it then. > > > > Dan -Michael