Re: [PATCH] Changes to interpreter op table and simplified DO_OP
Oops; that'll teach me to submit things before a cvs update. The generate.pl I just sent is out-of-date with regards to CVS. Attached is an updated version. (I haven't seen my prior mail go through yet; I'm guessing this is the list being slow, but it might be a problem with my local mail system. Just in case, I'm sending this from a different machine. If this arrives without my prior message, that means my mail system is screwy. :) - Damien generate.pl
[PATCH] Changes to interpreter op table and simplified DO_OP
All -- I wanted to have a unified op func, name, argc and argtype[] member in the interpreter struct, and that led me to make all the changes in this patch. I don't know if I've gone too far, but DO_OP is simpler now, and things still seem to run for me. Anyone else interested in trying this out? Dan? Does this fly in the face of your overall design, or is this a good thing? Regards, -- Gregor _ / perl -e 'srand(-2091643526); print chr rand 90 for (0..4)' \ Gregor N. Purdy [EMAIL PROTECTED] Focus Research, Inc.http://www.focusresearch.com/ 8080 Beckett Center Drive #203 513-860-3570 vox West Chester, OH 45069 513-860-3579 fax \_/ ? ;q ? op_info.patch ? t/inc.pasm ? t/jumpoob.pasm ? t/jumpsub.pasm ? t/substr.pasm ? t/jump2.pasm ? t/jump3.pasm ? t/jump4.pasm ? t/runoob.pasm ? t/test.pbc.x ? t/op/integer8.pasm ? t/op/integer8.out ? t/op/integer9.pasm ? t/op/integer9.out ? t/op/integer10.pasm ? t/op/integer10.out ? t/op/integer11.pasm ? t/op/integer11.out ? t/op/integer12.pasm ? t/op/integer12.out ? t/op/integer13.pasm ? t/op/integer13.out ? t/op/integer14.pasm ? t/op/integer14.out ? t/op/integer15.pasm ? t/op/integer15.out ? t/op/integer16.pasm ? t/op/integer16.out ? t/op/integer17.pasm ? t/op/integer17.out ? t/op/integer18.pasm ? t/op/integer18.out ? t/op/integer19.pasm ? t/op/integer19.out ? t/op/integer20.pasm ? t/op/integer20.pbc ? t/op/integer20.out ? t/op/number6.pasm ? t/op/number6.out ? t/op/number7.pasm ? t/op/number7.out ? t/op/number8.pasm ? t/op/number8.out ? t/op/number9.pasm ? t/op/number9.out ? t/op/number10.pasm ? t/op/number10.out ? t/op/number11.pasm ? t/op/number11.out ? t/op/number12.pasm ? t/op/number12.out ? t/op/number13.pasm ? t/op/number13.out ? t/op/number14.pasm ? t/op/number14.out ? t/op/number15.pasm ? t/op/number15.out ? t/op/number16.pasm ? t/op/number16.out ? t/op/number17.pasm ? t/op/number17.out ? t/op/number18.pasm ? t/op/number18.pbc ? t/op/number18.out Index: build_interp_starter.pl === RCS file: /home/perlcvs/parrot/build_interp_starter.pl,v retrieving revision 1.11 diff -u -r1.11 build_interp_starter.pl --- build_interp_starter.pl 2001/09/19 20:05:06 1.11 +++ build_interp_starter.pl 2001/09/19 22:20:19 @@ -2,6 +2,9 @@ use strict; use Parrot::Opcode; +my %opcodes= Parrot::Opcode::read_ops(); +my $opcode_fingerprint = Parrot::Opcode::fingerprint(); + open INTERP, include/parrot/interp_guts.h or die Can't open include/parrot/interp_guts.h, $!/$^E; print INTERP CONST; @@ -14,57 +17,35 @@ * Best not edit it */ -#define BUILD_TABLE(x) do { \\ +op_info_table_t builtin_op_info_table = { +/* TODO: (void *) casting here sucks! */ CONST -my %opcodes= Parrot::Opcode::read_ops(); -my $opcode_fingerprint = Parrot::Opcode::fingerprint(); - for my $name (sort {$opcodes{$a}{CODE} = $opcodes{$b}{CODE}} keys %opcodes) { -print INTERP \tx[$opcodes{$name}{CODE}] = (void*)$name; \\\n; -} -print INTERP } while (0);\n; +printf INTERP { (void *)%-12s, %-14s, %d, { , + $name, \$name\, $opcodes{$name}{ARGS}; - -# -# BUILD_NAME_TABLE macro: -# - -print INTERP CONST; -#define BUILD_NAME_TABLE(x) do { \\ -CONST +if ($opcodes{$name}{ARGS}) { + printf INTERP %-18s }, join(, , map { '$_' } @{$opcodes{$name}{TYPES}}); +} else { +printf INTERP %-18s }, '*'; +} -for my $name (sort {$opcodes{$a}{CODE} = $opcodes{$b}{CODE}} keys %opcodes) { -print INTERP \tx[$opcodes{$name}{CODE}] = \$name\; \\\n; -} -print INTERP } while (0);\n; - - -# -# BUILD_ARG_TABLE macro: -# - -print INTERP CONST; -#define BUILD_ARG_TABLE(x) do { \\ -CONST - -for my $name (sort {$opcodes{$a}{CODE} = $opcodes{$b}{CODE}} keys %opcodes) { -print INTERP \tx[$opcodes{$name}{CODE}] = $opcodes{$name}{ARGS}; \\\n; +printf INTERP }, /* %4d */\n, $opcodes{$name}{CODE}; } -print INTERP } while (0);\n; +print INTERP };\n\n; # # Spit out the DO_OP function # +# w = code +# z = interpreter +# print INTERP EOI; -#define DO_OP(w,x,y,z) do { \\ -x = (void *)z-opcode_funcs; \\ -y = (opcode_t* (*)())x[*w]; \\ -w = (y)(w,z); \\ - } while (0); +#define DO_OP(PC,INTERP) PC = ((INTERP-opcode_info)[*PC].func)(PC,INTERP); EOI # Spit out the OPCODE_FINGERPRINT macro Index: interpreter.c === RCS file: /home/perlcvs/parrot/interpreter.c,v retrieving revision 1.18 diff -u -r1.18 interpreter.c --- interpreter.c 2001/09/19 20:05:06 1.18 +++ interpreter.c 2001/09/19 22:20:19 @@ -13,9 +13,10 @@ #include parrot/parrot.h #include parrot/interp_guts.h -char *op_names[2048]; -int op_args[2048]; +/* char *
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
On Wed, Sep 19, 2001 at 06:23:41PM -0400, Gregor N. Purdy wrote: -print INTERP \tx[$opcodes{$name}{CODE}] = (void*)$name; \\\n; -} -print INTERP } while (0);\n; +printf INTERP { (void *)%-12s, %-14s, %d, { , + $name, \$name\, $opcodes{$name}{ARGS}; This is so much more confusing. :( +#define DO_OP(PC,INTERP) PC = ((INTERP-opcode_info)[*PC].func)(PC,INTERP); I'm highly unconvinced that this is as portable as you'd like to think it is. + /* TODO: Why not 'op_info_table_t opcode_info'? */ Because we want to keep our developers sane. Simon -- Rule 3: If the character is comprised of a container without another radical, then Rule 3 will not apply.
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
At 06:23 PM 9/19/2001 -0400, Gregor N. Purdy wrote: All -- I wanted to have a unified op func, name, argc and argtype[] member in the interpreter struct, and that led me to make all the changes in this patch. I don't know if I've gone too far, but DO_OP is simpler now, and things still seem to run for me. Anyone else interested in trying this out? Dan? Does this fly in the face of your overall design, or is this a good thing? Cool, but not a good thing. The problem with it is there's a lot of extraneous stuff scattered in the function table structure. That's going to reduce the L1 cache hit rate, and I'd rather not do that. Separate arrays would be fine, but just not unified like that. Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
-print INTERP \tx[$opcodes{$name}{CODE}] = (void*)$name; \\\n; -} -print INTERP } while (0);\n; +printf INTERP { (void *)%-12s, %-14s, %d, { , + $name, \$name\, $opcodes{$name}{ARGS}; This is so much more confusing. :( It may be a little less clear to read the code, but the output is so much more readable in the generated file. A good trade-off in my book (my book allows printf :-) +#define DO_OP(PC,INTERP) PC = ((INTERP-opcode_info)[*PC].func)(PC,INTERP); I'm highly unconvinced that this is as portable as you'd like to think it is. Yeah. I'm not a portability guru. Obviously the meaning is the same to a human C programmer and we remove the (explicit) temporaries. I think this is more *redable*, but I can't speek to whether it is equally *compilable*. I don't see any reason why it wouldn't be, but as I said, I don't know all there is to know about portability when it comes to stuff like this. I'm hoping to learn, though, if someone tries it and they tell me how it barfs. + /* TODO: Why not 'op_info_table_t opcode_info'? */ Because we want to keep our developers sane. The comment is there because it doesn't compile. I don't know what the developer sanity effects would be if it did compile. Regards, -- Gregor
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
Dan? Does this fly in the face of your overall design, or is this a good thing? Cool, but not a good thing. The problem with it is there's a lot of extraneous stuff scattered in the function table structure. That's going to reduce the L1 cache hit rate, and I'd rather not do that. Separate arrays would be fine, but just not unified like that. (This may be free software, but them ain't free cycles! :-) Suppose I put back the function-pointers-only array and remove the function pointers from the new one (partway back to the way it was). Do you see other problems with this? Simon had some portability and readability concerns. The former I don't see (but would like to), and the latter I...well...don't see :-) Regards, -- Gregor
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
At 09:23 PM 9/19/2001 -0400, Gregor N. Purdy wrote: Dan? Does this fly in the face of your overall design, or is this a good thing? Cool, but not a good thing. The problem with it is there's a lot of extraneous stuff scattered in the function table structure. That's going to reduce the L1 cache hit rate, and I'd rather not do that. Separate arrays would be fine, but just not unified like that. (This may be free software, but them ain't free cycles! :-) Damn straight. :) Making more work for us is fine if it makes the ultimate interpreter faster. Suppose I put back the function-pointers-only array and remove the function pointers from the new one (partway back to the way it was). Do you see other problems with this? I want the table we look function pointers up in to be *just* function pointers and nothing but. (I'm also considering analyzing the code the compiler spits out and ordering the opcodes such that ones commonly executed together are next to one another in the table) The big reason here is cache coherency, and here's a (simplified) explanation of why it's important. When the CPU fetches data from memory into its cache, it usually fetches a good-sized chunk, (called a cache line) anywhere from 8 to 64 bytes at once depending on the CPU architecture. Getting that data in is reasonably slow, especially if it has to come in from main memory. (We're talking 10 to 100 cycles) Once it's in the cache, though, accessing it takes a cycle or two. Generally speaking a single function table entry will take less than a whole cache line. That means we get the rest of the data in that cache line loaded free, and we don't have to pay to fault it in later. If we have other stuff in the table, though, we're loading in useless data. (Useless in the sense that we're not going to use it) Basically we're getting a free load on most architectures, so we ought to use it where we can. (And it doesn't hurt us on those architectures where we don't have it) Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
At 09:16 PM 9/19/2001 -0400, Gregor N. Purdy wrote: -print INTERP \tx[$opcodes{$name}{CODE}] = (void*)$name; \\\n; -} -print INTERP } while (0);\n; +printf INTERP { (void *)%-12s, %-14s, %d, { , + $name, \$name\, $opcodes{$name}{ARGS}; This is so much more confusing. :( It may be a little less clear to read the code, but the output is so much more readable in the generated file. A good trade-off in my book (my book allows printf :-) People will generally be reading the code, not the output in the generated file. I'd prefer to optimize readability in the core files as opposed to the generated ones when we have to choose. +#define DO_OP(PC,INTERP) PC = ((INTERP-opcode_info)[*PC].func)(PC,INTERP); I'm highly unconvinced that this is as portable as you'd like to think it is. Yeah. I'm not a portability guru. Obviously the meaning is the same to a human C programmer and we remove the (explicit) temporaries. I think this is more *redable*, but I can't speek to whether it is equally *compilable*. I don't see any reason why it wouldn't be, but as I said, I don't know all there is to know about portability when it comes to stuff like this. I'm hoping to learn, though, if someone tries it and they tell me how it barfs. Odds are the temps are irrelevant to the ultimate code speed. Any compiler worth its salt will optimize them properly, and the ones that suck, well, there's not much we can do about that. :) Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [PATCH] Changes to interpreter op table and simplified DO_OP
On Wed, 19 Sep 2001, Dan Sugalski wrote: Basically we're getting a free load on most architectures, so we ought to use it where we can. (And it doesn't hurt us on those architectures where we don't have it) 1) Does that make us freeloaders? 2) I guess the architecture designers are not Heinlein fans, or they would realize that TANSTAAFL(oad). : Sorry, couldn't resist. Dave