Re: Dynamic oplibs - intermediate summary

2003-10-16 Thread 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.

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


Re: Dynamic oplibs - intermediate summary

2003-10-16 Thread Dan Sugalski
On Thu, 16 Oct 2003, Nicholas Clark wrote:

 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


Dynamic oplibs - intermediate summary

2003-10-16 Thread Leopold Toetsch
Now all run cores[2] are able to execute dynoplibs/test.pasm [1].
This is currently done for all cores except the function (slow) core by 
running the wrapper__ opcode, which calls the real function in the 
parrot function core.

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 Cloadlib 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 Cnoops 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 
Cloadlib 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.



Re: Dynamic oplibs - intermediate summary

2003-10-16 Thread Leopold Toetsch
Nicholas Clark [EMAIL PROTECTED] wrote:
 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.

[ 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