Re: [PATCH] Changes to interpreter op table and simplified DO_OP

2001-09-20 Thread Damien Neil

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

2001-09-19 Thread Gregor N. Purdy

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

2001-09-19 Thread Simon Cozens

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

2001-09-19 Thread Dan Sugalski

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

2001-09-19 Thread Gregor N. Purdy



  -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

2001-09-19 Thread Gregor N. Purdy


 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

2001-09-19 Thread Dan Sugalski

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

2001-09-19 Thread Dan Sugalski

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

2001-09-19 Thread Dave Storrs



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