Re: PMCs, setting, and suchlike things
On Thu, 14 Feb 2002, Dave Mitchell wrote: $foo would first be a Dog, then a FireHydrant. When it changed to a FireHydrant the previous contents would get blown away. Hmmm - how do we distinguish between a plain scalar that is temporarily typed, and a 'proper' permanently-typed scalar? eg in the following my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); you would expect $spot to always remain a dog no matter what, and will throw a run-time (or compile time) error if it can't think of a way of making itself into a doggish cat. I think you're thinking at too high a level to make much sense of what the vtables should be doing. A better example to drive your mind would be: tie $foo, 'Baa'; $foo = 12; In which case the $foo PMC will know that it is somehow tied, and dispatch control to an appropriate bit of perl code. it's current vtable pointer, and if so, under what circumstances are we allowed to change the pointer? Do we need a PMC flag saying that our type is fixed? And if so, how do we handle PMCs define how a variable behaves in different circumstances. We can change the pointer in every instance except those where the receiving PMC does not let us, in general a PMC will be happy to lose its identity. Alex Gough -- #!/usr/bin/perl use Quantum::Entanglement qw(:DEFAULT :complex); $language = entangle(1,'python',1/i,'C',i*i,'Perl',1/i**2,'Java',i**5,'C#'); print Just another $language hacker,\n if $language eq 'Perl';
Re: PMCs, setting, and suchlike things
On Thu, Feb 14, 2002 at 02:10:20PM +, Dave Mitchell wrote: 2. If so, how do we distinguish between two PMCs, both of whose vtable pointers currently point to the 'Dog' vtable, but one of whom has been delared as type Dog and so should never have it's vatble pointer updated, and the other which started off as a 'plain' PMC, has temporariky becomes a Dog by beeing assigned to from a Dog value, but will change again the next time we assign something to it? I may be way off here, but why does Parrot need to know its a Dog ? Thats a perl level thing. To Parrot the PMC is an object, Dog would be a property of the value, not the variable. At the Parrot level the difference between my Dog $spot = new Dog; my $scalar = new Dog; is that the prior would have an extra vtable entry to handle assignment. That vtable method only needs to check that what is being assigned is a PMC of the right type. Graham.
Re: PMCs, setting, and suchlike things
At 11:46 AM + 2/14/02, Dave Mitchell wrote: Dan Sugalski [EMAIL PROTECTED] wrote: Right, for typed variables. Most variables (i.e. anything you declared with a plain my $foo or our @bar) are untyped and can change their types as needed. If you did: my $foo; $foo = Dog.new(); $foo = FireHydrant.new(); $foo would first be a Dog, then a FireHydrant. When it changed to a FireHydrant the previous contents would get blown away. Hmmm - how do we distinguish between a plain scalar that is temporarily typed, and a 'proper' permanently-typed scalar? eg in the following my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); you would expect $spot to always remain a dog no matter what, and will throw a run-time (or compile time) error if it can't think of a way of making itself into a doggish cat. There's a flag in the flags field to mark the PMC as a permanent type or not. It's insufficient for Type X or child of X things, though. Or to put it another way, is the type of a PMC determined purely by it's current vtable pointer, and if so, under what circumstances are we allowed to change the pointer? The variable's vtable functions are the only things allowed to change that pointer. The circumstances under which they change it are up to the authors of the vtables. For standard types we need to hash some things out for it. And can we indeed conflate the concepts of type as defined by a vtable pointer, and Perl-level type? Will there always be a seaprate vtable for each Perl-level type There will be at least one vtable per perl-level type, yes. Each package and class gets at least one, as do any lower-level user-defined types. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: PMCs, setting, and suchlike things
Dan Sugalski [EMAIL PROTECTED] To: Dave Mitchell [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] 02/14/2002 10:23 cc: AM Subject: Re: PMCs, setting, and suchlike things my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); In this case all types are known at compile time. Why would we relegate this to a runtime vtable check or bit flag? There's a flag in the flags field to mark the PMC as a permanent type or not. It's insufficient for Type X or child of X things, though. This should be sufficient. The higher level language should take care of this kind of checking anyway, especially since much of it is able to be done at compile. I think in cases of ambiguous combinations you could just fall back on stringifing the object, right? I might be missing the whole issue here. -Melvin Smith IBM :: Atlanta Innovation Center [EMAIL PROTECTED] :: 770-835-6984
Re: PMCs, setting, and suchlike things
On Thu, 14 Feb 2002, Melvin Smith wrote: my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); In this case all types are known at compile time. Why would we relegate this to a runtime vtable check or bit flag? There's no reason to suspect that Dog::new will actually return a Dog object or that Cat::new won't, that's just not Perl. If we're to check the type of the value being stored in $spot, we pretty much have to do it at run time. Alex Gough -- He may look like an idiot, and talk like an idiot...but don't let that fool you. He really is an idiot.
Re: PMCs, setting, and suchlike things
At 3:48 PM + 2/14/02, Alex Gough wrote: On Thu, 14 Feb 2002, Melvin Smith wrote: my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); In this case all types are known at compile time. Why would we relegate this to a runtime vtable check or bit flag? There's no reason to suspect that Dog::new will actually return a Dog object or that Cat::new won't, that's just not Perl. If we're to check the type of the value being stored in $spot, we pretty much have to do it at run time. Yup. There's no guarantee that any particular sub or method call will return what we think it does, and without digging into the code we can't tell. (Well, short of prototypes, at least) -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: PMCs, setting, and suchlike things
Alex Gough [EMAIL PROTECTED]To: Melvin Smith/ATLANTA/Contr/IBM@IBMUS ford.ac.uk cc: [EMAIL PROTECTED] Subject: Re: PMCs, setting, and suchlike things 02/14/2002 10:48 AM On Thu, 14 Feb 2002, Melvin Smith wrote: my Dog $spot = Dog.new(waggly tail); $spot = Cat.new(); In this case all types are known at compile time. Why would we relegate this to a runtime vtable check or bit flag? There's no reason to suspect that Dog::new will actually return a Dog object or that Cat::new won't, that's just not Perl. If we're to Gotcha, I was letting my C++ get in the way. :) -Melvin Smith IBM :: Atlanta Innovation Center [EMAIL PROTECTED] :: 770-835-6984
Re: PMCs, setting, and suchlike things
At 3:53 PM + 2/14/02, Dave Mitchell wrote: My outstanding niggle is when a typed variable is undef. I guess we need a generic Perl_Undef_But_Typed vtable type, which behaves mostly like the PerlUndef type, but saves a pointer to its 'real' vtable in self-data or whatever. When it's assigned to, it upgrades itself to its real type, then passes control to it's real type's assign method. That's a good point. I'll have to think about that a little bit. We could either have an undef flag or something and take definedness entirely out of the hands of the vtables, or use the X or child of X mechnanism to allow for undefs as well. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [PATCH] Fix calculation of byte code end
On Wed, Feb 13, 2002 at 10:43:38PM -0500, Jason Gloudon wrote: The type changes in struct Packfile break the pointer math used in a few places to calculate the address of the end of the loaded byte code. This causes segfaults in build_asm in jit.c when using -j. It also breaks the bounds checking on opcode address in runops_slow_core. The patch adds the necessary cast to correct the code_end calculations. Personally, I think it makes much more sense to have everything outside of the packfile think in terms of opcode_t*, not char*. The following untested but straightforward patch eliminates all typecasts from the relevant chunks of code. And adds them back in to pdump.c, at the points where it really is meant to be converting a char* array to an opcode_t* array. Oh, oops. Except it collided with my previously submitted but unapplied patch to fix the parsing of complex control-flow macros like goto ADDRESS(( branch ? expr OFFSET($2) : expr NEXT() )). I did that one to fix something with the jit, I seem to recall. Well, they're rolled together here, let me know if you want me to split them apart. The casting patch is all the files in this patch except Op.pm, and contains only the macro redefinitions in C.pm and CPrederef.pm. Index: pdump.c === RCS file: /home/perlcvs/parrot/pdump.c,v retrieving revision 1.8 diff -a -u -r1.8 pdump.c --- pdump.c 1 Jan 2002 19:49:11 - 1.8 +++ pdump.c 14 Feb 2002 19:09:22 - @@ -16,7 +16,7 @@ main(int argc, char **argv) { struct stat file_stat; int fd; -char *packed; +opcode_t *packed; size_tpacked_size; struct PackFile * pf; struct Parrot_Interp *interpreter = make_interpreter(0); @@ -43,7 +43,7 @@ packed_size = file_stat.st_size; #ifndef HAS_HEADER_SYSMMAN -packed = mem_sys_allocate(packed_size); +packed = (opcode_t *) mem_sys_allocate(packed_size); if (!packed) { printf(Can't allocate, code %i\n, errno); @@ -52,7 +52,7 @@ read(fd, (void*)packed, packed_size); #else -packed = mmap(0, packed_size, PROT_READ, MAP_SHARED, fd, (off_t)0); +packed = (opcode_t *) mmap(0, packed_size, PROT_READ, MAP_SHARED, fd, (off_t)0); if (!packed) { printf(Can't mmap, code %i\n, errno); Index: interpreter.c === RCS file: /home/perlcvs/parrot/interpreter.c,v retrieving revision 1.69 diff -a -u -r1.69 interpreter.c --- interpreter.c 14 Feb 2002 05:53:58 - 1.69 +++ interpreter.c 14 Feb 2002 19:09:24 - @@ -61,14 +61,14 @@ runops_generic (opcode_t * (*core)(struct Parrot_Interp *, opcode_t *), struct Parrot_Interp *interpreter, opcode_t * pc) { opcode_t * code_start; -UINTVALcode_size; +UINTVALcode_size; /* in opcodes */ opcode_t * code_end; check_fingerprint(interpreter); -code_start = (opcode_t *)interpreter-code-byte_code; -code_size = interpreter-code-byte_code_size; -code_end = (opcode_t *)((char *)interpreter-code-byte_code + code_size); +code_start = interpreter-code-byte_code; +code_size = interpreter-code-byte_code_size / sizeof(opcode_t); +code_end = interpreter-code-byte_code + code_size; pc = core(interpreter, pc); @@ -286,15 +286,15 @@ runops_jit (struct Parrot_Interp *interpreter, opcode_t * pc) { #ifdef HAS_JIT opcode_t * code_start; -UINTVALcode_size; +UINTVALcode_size; /* in opcodes */ opcode_t * code_end; jit_f jit_code; check_fingerprint(interpreter); -code_start = (opcode_t *)interpreter-code-byte_code; -code_size = interpreter-code-byte_code_size; -code_end = (opcode_t *)((char *)interpreter-code-byte_code + code_size); +code_start = interpreter-code-byte_code; +code_size = interpreter-code-byte_code_size / sizeof(opcode_t); +code_end = interpreter-code-byte_code + code_size; jit_code = build_asm(interpreter, pc, code_start, code_end); #ifdef ALPHA @@ -337,15 +337,15 @@ runops_prederef (struct Parrot_Interp *interpreter, opcode_t * pc, void ** pc_prederef) { opcode_t * code_start; -UINTVALcode_size; +UINTVALcode_size; /* in opcodes */ opcode_t * code_end; void **code_start_prederef; check_fingerprint(interpreter); -code_start = (opcode_t *)interpreter-code-byte_code; -code_size = interpreter-code-byte_code_size; -code_end = (opcode_t *)((char *)interpreter-code-byte_code + code_size); +code_start = interpreter-code-byte_code; +code_size = interpreter-code-byte_code_size / sizeof(opcode_t); +code_end = interpreter-code-byte_code + code_size; code_start_prederef = pc_prederef; Index: runops_cores.c === RCS file:
Forth engine techniques for faster byte code interpreter. (indirect threaded interpreter)
The librep virtual machine uses a technique taken from Forth engines called indirect threading. That's not threading as in multithreading or pthreads... You'll have to read about it for yourselves, since I've not the knowledge, time, or the inclination to write a long essay on the subject. I can tell you it exists and show you where to find out about it, however. When GCC is the compiler, rep uses the address of label and computed goto features to build a jump table into the interpreter/decoder loop. So rather than test, fail, branch, test, fail, branch, ..., test, hit, execute, branch in a long switch statement, it uses the opcode as the index into a jump table, and does a goto table[op] instead. When it's built with some olde slowunuchs compiler, it falls back to being a switch statement, through fancy use of the CPP macro system. It's really very amazing and clever. From URL:http://www.geocrawler.com/archives/3/688/2001/3/0/5397900/: @InProceedings{ertl93, author = M. Anton Ertl, title =A Portable {Forth} Engine, booktitle =EuroFORTH '93 conference proceedings, year = 1993, address = Mari\'ansk\'e L\'azn\`e (Marienbad), url = http://www.complang.tuwien.ac.at/papers/ertl93.ps.Z;, } Additionally, a search for this author, paper, and/or subject on CiteSeer may prove fruitful... (bookmark this one!) URL:http://citeseer.nj.nec.com/ The librep byte code engine is very fast. Anyone who has used sawfish can attest to it's quickness. My guess is that a good look at librep (and some Rep Lisp code) might prove very interesting. Surely John Harper has already encountered many of the similar problems the Parrot developers are faced with! URL:http://librep.sourceforge.net/ The list archives there are probably worth mining, so bring your reading headlamp when you visit the list mine under the source forge. I would really like to see Parrot able to run rep lisp/scheme and guile with goops also. Do you know about them? It's worth spending some time to research, IMHO, so put your googles on guile's goops! (and click on that headlamp in their mailing list archives also.) ... and I've heard that rscheme has a real time generational garbage collector of some kind. I wonder if it's readable enough to use as a guide, portable enough to rip out and install, or even worth the bother? (I'm not good enough at it to understand the thing yet.) [ I sail a coffee mug in the general direction of a wall... Bring us WATER, dag nab it. I want something _healthy_ to drink so my brain doesn't break. ] -- mailto: (Karl M. Hegbloom) [EMAIL PROTECTED] Free the Software http://www.debian.org/social_contract http://www.microsharp.com phone://USA/WA/360-260-2066
Your mission...
If you choose to accept it, is to dig out the computed goto and switch runops cores from the archives, dust 'em off and get them up to snuff with the current sources. Takers, anone? -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [Patch] Some de-linting [APPLIED]
At 12:21 AM -0500 2/13/02, Josh Wilmes wrote: I've tweaked the lint target somewhat and fixed a few of the things it finds. Attaching the patch as well as the current lint output. Applied, thanks. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
[Patch] function pointer handling
This patch removes unnecessary function pointer conversions (which have undefined behavior in ANSI C). This gets rid of several warnings encountered with the lcc compiler and isolates our function pointer misbehavior to only the jit code. --Josh Index: core.ops === RCS file: /home/perlcvs/parrot/core.ops,v retrieving revision 1.94 diff -u -r1.94 core.ops --- core.ops15 Feb 2002 02:30:02 - 1.94 +++ core.ops15 Feb 2002 06:16:31 - @@ -2227,22 +2227,22 @@ inline op save(in INT) { INTVAL i = $1; - stack_push(interpreter, interpreter-user_stack, i, STACK_ENTRY_INT, NULL); + stack_push(interpreter, interpreter-user_stack, i, STACK_ENTRY_INT, +STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in NUM) { - stack_push(interpreter, interpreter-user_stack, ($1), STACK_ENTRY_FLOAT, NULL); + stack_push(interpreter, interpreter-user_stack, ($1), STACK_ENTRY_FLOAT, +STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in PMC) { - stack_push(interpreter, interpreter-user_stack, $1, STACK_ENTRY_PMC, NULL); + stack_push(interpreter, interpreter-user_stack, $1, STACK_ENTRY_PMC, +STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in STR) { - stack_push(interpreter, interpreter-user_stack, $1, STACK_ENTRY_STRING, NULL); + stack_push(interpreter, interpreter-user_stack, $1, STACK_ENTRY_STRING, +STACK_CLEANUP_NULL); goto NEXT(); } @@ -2339,7 +2339,7 @@ =cut inline op bsr (in INT) { - stack_push(interpreter, interpreter-control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, NULL); + stack_push(interpreter, interpreter-control_stack, expr NEXT(), +STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); goto OFFSET($1); } Index: interpreter.c === RCS file: /home/perlcvs/parrot/interpreter.c,v retrieving revision 1.69 diff -u -r1.69 interpreter.c --- interpreter.c 14 Feb 2002 05:53:58 - 1.69 +++ interpreter.c 15 Feb 2002 06:16:32 - @@ -88,7 +88,7 @@ */ static void * prederef_oplib_handle = NULL; -static oplib_init_f prederef_oplib_init = NULL; +static oplib_init_f prederef_oplib_init = (oplib_init_f)NULLfunc; static op_lib_t * prederef_oplib= NULL; static INTVAL prederef_op_count = 0; static op_info_t * prederef_op_info = NULL; @@ -195,7 +195,7 @@ Parrot_dlclose(prederef_oplib_handle); prederef_oplib= NULL; - prederef_oplib_init = NULL; + prederef_oplib_init = (oplib_init_f)NULLfunc; prederef_oplib_handle = NULL; } @@ -466,8 +466,8 @@ /* Initialize interpreter's flags */ interpreter-flags = flags; - interpreter-warns = mem_sys_allocate(sizeof(struct warnings_t)); - PARROT_WARNINGS_off(interpreter, PARROT_WARNINGS_ALL_FLAG); +interpreter-warns = mem_sys_allocate(sizeof(struct warnings_t)); +PARROT_WARNINGS_off(interpreter, PARROT_WARNINGS_ALL_FLAG); interpreter-pmc_count = 0; interpreter-string_count = 0; Index: ops2c.pl === RCS file: /home/perlcvs/parrot/ops2c.pl,v retrieving revision 1.17 diff -u -r1.17 ops2c.pl --- ops2c.pl14 Feb 2002 19:33:05 - 1.17 +++ ops2c.pl15 Feb 2002 06:16:33 - @@ -187,7 +187,7 @@ print SOURCE @op_func_table; print SOURCE END_C; - NULL + (op_func${suffix}_t)0 /* NULL function pointer */ }; Index: stacks.c === RCS file: /home/perlcvs/parrot/stacks.c,v retrieving revision 1.19 diff -u -r1.19 stacks.c --- stacks.c15 Feb 2002 02:30:02 - 1.19 +++ stacks.c15 Feb 2002 06:16:33 - @@ -97,7 +97,7 @@ */ void stack_push(struct Parrot_Interp *interpreter, Stack stack, - void *thing, INTVAL type, void (*cleanup)(Stack_Entry)) + void *thing, INTVAL type, stack_cleanup_method_t cleanup) { Stack_Chunk chunk = stack-prev; Stack_Entry entry = chunk-entry[chunk-used]; Index: string.c === RCS file: /home/perlcvs/parrot/string.c,v retrieving revision 1.46 diff -u -r1.46 string.c --- string.c5 Feb 2002 11:41:27 - 1.46 +++ string.c15 Feb 2002 06:16:34 - @@ -151,8 +151,8 @@ const CHARTYPE *type, STRING **dest_ptr) { STRING *dest; -CHARTYPE_TRANSCODER transcoder1 = NULL; -CHARTYPE_TRANSCODER transcoder2 = NULL; +CHARTYPE_TRANSCODER transcoder1 = (CHARTYPE_TRANSCODER)NULLfunc; +CHARTYPE_TRANSCODER transcoder2 = (CHARTYPE_TRANSCODER)NULLfunc; char *srcstart; char *srcend; char *deststart; Index: include/parrot/parrot.h === RCS file: /home/perlcvs/parrot/include/parrot/parrot.h,v retrieving revision 1.25 diff -u -r1.25 parrot.h --- include/parrot/parrot.h 8 Feb 2002 11:42:13