Dan Sugalski <[EMAIL PROTECTED]> wrote: > At 5:19 PM +0100 3/19/05, Leopold Toetsch wrote: >>1) builtin methods are living in a class namespace e.g. >> >> Float."cos" >> ParrotIO."open" # unimplemented
> I'm way out of the loop and may have been dealt with in prior mail, > but are we doing real method calls for cos() and suchlike things? > That seems... sub-optimal for speed reasons. With the help of the PIC it'll translate to an one-time lookup per call site aka bytecode location. The lookup result is additionally cached in the method cache, which is pretty fast. The "method call" will translate eventually to an opcode like: call_PP "cos", Px, Py (we gonna have a fair amount of methods with this signature, so that a specialized opcode should be ok) The actual call then looks like: pic_cache = $1 # replaces the method name in bytecode if ($3->vtable->type == pic_cache->type) $2 = (pic_cache->nci.function)(interp, $3) else // consider ~3 more cache slots else // lookup the method The speed overhead compared to a dedicated vtable slot is minimal as that will call directly the C function - not the NCI wrapper. A further optimization could inline the function call for e.g. Float.cos if ($3->vtable->type == enum_class_Float) { FLOATVAL l, r = PMC_num_val($3); l = cos(r); ... > I've been thinking it may be worth pulling out some groups of > semi-commonly used functions that should be fast but still > PMC-class-specific, and thus not methods, into sub-tables hanging off > the vtable. Well, yes I'd like to have the vtable split into pieces. The vtable structure is just too big and by far not all functionality is needed by all PMCs: sizeof(VTABLE) 604 # 32-bit machine > ... Most of the semi-high-level string functions (basically > everything that may be delegated to the charset/encoding layers) > would be a candidate for this. Possibly the standard trig functions > too. I'd say: all that maybe used internally by the interpreter should have a vtable slot. Trig functions and other stuff can simply be done by a method call. One advantage is expandability, e.g .namespace ["Complex"] .sub cos ... is all to override (or create) a new method. During recompilation the "call_PP" opcode can directly be replaced by another variant that calls the PIR code from witin the same run-loop, without any delegation PMC and secondary run-loop. And the second is: having a vtable for all these functions needs an opcode too. We have 1500 opcodes and are already hitting compiler limits e.g. in the switch core. We can't afford to add another bunch of opcodes to get PMC versions of all the native type opcodes. The call_PP "meth", Px, Py opcode covers all such methods with that signature. Float.cos might be a suboptimal example, but we need a lot more library code e.g. $(perldoc POSIX) and what not. The whole library stuff needs just a namespace and an implementation either as PIR, NCI, or in a PMC class file. The call syntax from the PIR level looks like a method call or a plain opcode: .sub main @MAIN .local pmc o, m, cl o = getstdout $I0 = o."puts"("ok 1\n") puts $I0, o, "ok 2\n" $I0 = "puts"(o, "ok 3\n") m = getattribute o, "puts" $I0 = m("ok 4\n") cl = getclass "ParrotIO" $I0 = cl."puts"(o, "ok 5\n") .end leo