Cores with an address table for function dispatch (CGoto, CGP) get a new
address table, where all new entries are pointing to the wrapper__
opcode. CGP does use this address table only once when the opcode is
predereferenced.
The switch core calls the wrapper from the default case statement. JIT
emits a call to the wrapper function.
Next will be to try to find and load oplibs of the flavor of the
currently running core. If a program is run with the -C (CGP) core, the
dynop_register function will try to find the "..._cgp_ops_load" symbol
in the current dynamic oplib or in a separate file.
If this is successful, the opcode dispatch can use these opcodes
directly. The switch core will need some dispatch helpers (probably via
next function pointers containing loaded switch_cores. JIT is different.
As JIT code is unrolled, it IMHO can only call the function core (or CGP
again) for loaded opcodes.
When run from a source file, the C<loadlib> opcode is executed
immediately, so that the assembler can generate the bytecode with these
new opcodes. At runtime the loadlib finds the library already loaded and
does nothing (it could even be replaced by C<noop>s if its known, that
the program is to be run directly).
When a PBC is generated, and the code is run from that, now the
C<loadlib> is honored, when it is executed. So when there are multiple
loadlibs and these are not executed in the correct sequence, you'll get
nice crashes. This will be replaced (as Dan did lay out) by putting the
library PMCs into the metadata, so that library loading happens before
program startup and in the desired sequence.
Comments welcome,
leo
[1]
$ cat dynoplibs/test.pasm
...
loadlib P1, "myops_ops"
...
fortytwo I0
print I0
what_do_you_get_if_you_multiply_six_by_nine S0
...
$ make shared && export LD_LIBRARY_PATH=.:blib/lib
$ make -C dynoplibs clean all && make -C dynclasses && make libnci.so
$ parrot -j dynoplibs/test.pasm
in test
loaded myops_ops
loaded foo
loaded libnci
found 3 libs
Ops runtime/parrot/dynext/myops_ops.so
PMC runtime/parrot/dynext/foo.so
NCI libnci.so
the answer is: 42 aka fortytwo
[2] *if* platform supports dynamic loading of course.
I didn't look at EXEC, but as it does use JIT for building its code, it
could work too.
> As JIT code is unrolled, it IMHO can only call the function core (or CGP
> again) for loaded opcodes.
As is this would mean that the JIT can't JIT any opcodes that are brought
in by dynamically loaded classes, it would be pain for any heavy users of
custom classes.
Would it be beneficial (and feasible) to either provide a mechanism
(flag on the command line, flag in the bytecode, whatever parrot treats treats
a perl-level pragma as, etc, not sure) to either
a: disable the JIT until the main program starts (running on CG or some other
low startup cost core until then)
or
b: signal a (partial) re-JIT of something/everything after a library/
everything has loaded?
I've no idea how easy this might be. Or sensible.
Nicholas Clark
> On Thu, Oct 16, 2003 at 05:40:30PM +0200, Leopold Toetsch wrote:
>
> > As JIT code is unrolled, it IMHO can only call the function core (or CGP
> > again) for loaded opcodes.
>
> As is this would mean that the JIT can't JIT any opcodes that are brought
> in by dynamically loaded classes, it would be pain for any heavy users of
> custom classes.
This should only be temporary. If the right information is tagged in the
opcode library, then the JIT should be able to JIT the loaded ops (since
we do, after all, have to have the library loaded when we enter the
segment of code that uses the new ops. I don't mind just in time loading,
but I figure we ought to do it more than one or two ops before we execute
the new code. :)
Dan
>> As JIT code is unrolled, it IMHO can only call the function core (or CGP
>> again) for loaded opcodes.
> As is this would mean that the JIT can't JIT any opcodes that are brought
> in by dynamically loaded classes, it would be pain for any heavy users of
> custom classes.
[ snip ]
First - no pain. CGP and JIT rutimes are equally fast with PMC related
code. JIT only shines with natural int loops doing int and float
arithmetics.
When it comes to HLL there is no difference in performance - both cores
just do function calls.
Second - as said the JIT core does unroll opcodes, that is each JITted
assembly representation of any opcode is repeated in the execution
stream of the JITted instructions. While any other core branches around
in a fixed set of opcodes, the JIT runtime has a sequence of assembly
instructions representing these opcodes. Now when you load such opcodes
dynamically, there is no means to insert these into the current CPU
instructions - there is no hardware CPU representaion for loaded ops (if
there is any, the opcode would be in core, because it is important)
> Nicholas Clark
leo