[svn:parrot] r39253 - trunk/lib/Parrot/Pmc2c
bacek at svn.parrot.org
bacek at svn.parrot.org
Sat May 30 01:16:29 UTC 2009
Author: bacek
Date: Sat May 30 01:16:28 2009
New Revision: 39253
URL: https://trac.parrot.org/parrot/changeset/39253
Log:
Initial version of switch dispatch for MULTI
For rationale of this commit see TT#452. It should give massive speed boost
for basic (arithmetic) functions which uses only core PMCs. E.g.
examples/benchmark/primes2.pir for 5000 elements executed in ~10 seconds
instead of ~150 seconds.
Modified:
trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
Modified: trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
==============================================================================
--- trunk/lib/Parrot/Pmc2c/PMCEmitter.pm Sat May 30 01:16:08 2009 (r39252)
+++ trunk/lib/Parrot/Pmc2c/PMCEmitter.pm Sat May 30 01:16:28 2009 (r39253)
@@ -333,7 +333,18 @@
return $ret;
}
+=item C<pre_method_gen>
+
+Generate switch-bases VTABLE for MULTI
+
+=cut
+
sub pre_method_gen {
+ my ($self) = @_;
+
+ $self->gen_switch_vtable;
+
+ 1;
}
=item C<gen_methods()>
@@ -407,7 +418,7 @@
my $full_sig = $pmcname . "," . $method->{MULTI_full_sig};
my $functionname = 'Parrot_' . $pmcname . '_' . $method->name;
push @multi_names, [ $method->symbol, $short_sig, $full_sig,
- $pmcname, $functionname ];
+ $pmcname, $functionname, $method ];
}
return ( \@multi_names );
}
@@ -936,6 +947,130 @@
return $self->{vtable};
}
+=item C<gen_switch_vtable>
+
+Generate switch-bases VTABLE for MULTI
+
+=cut
+
+sub gen_switch_vtable {
+ my ($self) = @_;
+
+ # No cookies for DynPMC. At least not now.
+ return 1 if $self->is_dynamic;
+
+ # Convert list of multis to name->[(type,,ssig,fsig,ns,func)] hash.
+ my %multi_methods;
+ foreach (@{$self->find_multi_functions}) {
+ my ($name, $ssig, $fsig, $ns, $func, $method) = @$_;
+ my @sig = split ',', $fsig;
+ push @{ $multi_methods{ $name } }, [ $sig[1], $ssig, $fsig, $ns, $func, $method ];
+ }
+
+ # vtable methods
+ foreach my $method ( @{ $self->vtable->methods } ) {
+ my $vt_method_name = $method->name;
+ next if $vt_method_name eq 'class_init';
+
+ next if $self->implements_vtable($vt_method_name);
+ next unless exists $multi_methods{$vt_method_name};
+
+ my $multis = $multi_methods{$vt_method_name};
+
+ # Gather "case :"
+ my @cases = map { $self->generate_single_case($vt_method_name, $_) } @$multis;
+ my $cases = join "\n", @cases;
+
+ my $body = <<"BODY";
+ INTVAL type = VTABLE_type(INTERP, value);
+ switch(type) {
+$cases
+ }
+BODY
+
+ my $vtable = $method->clone({
+ body => Parrot::Pmc2c::Emitter->text($body),
+ });
+ $self->add_method($vtable);
+ }
+
+ 1;
+}
+
+# Generate signle case for switch VTABLE
+sub generate_single_case {
+ my ($self, $vt_method_name, $multi) = @_;
+
+ my ($type, $ssig, $fsig, $ns, $func, $impl) = @$multi;
+ my $case;
+
+ # Gather parameters names
+ my @parameters = map { s/\s*PMC\s*\*\s*//; $_ } split (',', $impl->parameters);
+ my $parameters = join ', ', @parameters;
+
+ if ($type eq 'DEFAULT' || $type eq 'PMC') {
+ # For default case we have to handle return manually.
+ my ($pcc_signature, $retval, $call_tail, $return)
+ = $self->gen_defaul_case_wrapping($ssig, @parameters);
+
+ $case = <<"CASE";
+ default:
+ if (type < enum_class_core_max)
+ return $func(INTERP, SELF, $parameters);
+ else {
+ $retval
+ Parrot_mmd_multi_dispatch_from_c_args(INTERP, "$vt_method_name", "$pcc_signature", SELF, $parameters$call_tail);
+ $return
+ }
+CASE
+ }
+ else {
+ $case = <<"CASE";
+ case enum_class_$type:
+ return $func(INTERP, SELF, $parameters);
+CASE
+ }
+
+ $case;
+}
+
+# Generate (pcc_signature, retval holder, pcc_call_tail, return statement)
+# for default case in switch.
+sub gen_defaul_case_wrapping {
+ my ($self, $ssig, @parameters) = @_;
+
+ my $letter = substr($ssig, 0, 1);
+ my $pcc_signature = "PP->" . $letter;
+ if ($letter eq 'I') {
+ return (
+ $pcc_signature,
+ "INTVAL retval;",
+ ', &retval',
+ 'return retval;',
+ );
+ }
+ elsif ($letter eq 'P') {
+ return (
+ $pcc_signature,
+ '',
+ ", &$parameters[1]",
+ "return $parameters[1];",
+ );
+ }
+ elsif ($letter eq 'v') {
+ return (
+ $pcc_signature,
+ '',
+ '',
+ 'return;',
+ );
+ }
+ else {
+ die "Can't handle signature $ssig!";
+ }
+}
+
+
1;
# Local Variables:
More information about the parrot-commits
mailing list