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

Reply via email to