tokuhirom's Blog

Faster.pm の最適化

Faster.pm がやってることは、基本的には Perl VM がやってる処理を C のコードにかきくだしただけなのです。生成されてる C のコードは以下のようなかんじだ。

ここからさらに最適化できれば、ぐっと速くできるのだけど。

#define PERL_NO_GET_CONTEXT
#define PERL_CORE

#include <assert.h>

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#if 1
# define faster_PUSHMARK_PREALLOC(count) while (PL_markstack_ptr + (count) >= PL_
markstack_max) markstack_grow ()
# define faster_PUSHMARK(p) *++PL_markstack_ptr = (p) - PL_stack_base
#else
# define faster_PUSHMARK_PREALLOC(count) 1
# define faster_PUSHMARK(p) PUSHMARK(p)
#endif

#define RUNOPS_TILL(op)                                         \
  while (nextop != (op))                                        \
    {                                                           \
      PERL_ASYNC_CHECK ();                                      \
      PL_op = nextop; nextop = (PL_op->op_ppaddr)(aTHX);        \
    }

OP *F485e855f8965caa3b40498ee2da71dcc (pTHX)
{
  register OP *nextop = (OP *)34431168L;
  faster_PUSHMARK_PREALLOC (1);
op_34431168: /* nextstate */
  PL_curcop = (COP *)nextop;
  PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
  FREETMPS;
  nextop = (OP *)34430960L;
  goto op_34430960;
op_34430960: /* pushmark */
  faster_PUSHMARK (PL_stack_sp);
  nextop = (OP *)34431264L;
  goto op_34431264;
op_34431264: /* aelemfast */
  { dSP; EXTEND (SP, 3); PUTBACK; }
  {
    AV *av = GvAV ((GV *)34279824L);
    SV **svp = av_fetch (av, 0, 0); SV *sv = svp ? *svp : &PL_sv_undef;
    if (SvGMAGICAL (sv)) sv = sv_mortalcopy (sv);
    dSP;
    PUSHs (sv);
    PUTBACK;
  }
  nextop = (OP *)34431424L;
  goto op_34431424;
op_34431424: /* const */
  { dSP; PUSHs ((SV *)34392504L); PUTBACK; }
  nextop = (OP *)34430720L;
  goto op_34430720;
op_34430720: /* add */
  PL_op = nextop; nextop = Perl_pp_add (aTHX);
  goto op_34431760;
op_34431760: /* const */
  { dSP; PUSHs ((SV *)34280232L); PUTBACK; }
  nextop = (OP *)34431040L;
  goto op_34431040;
op_34431040: /* print */
  PERL_ASYNC_CHECK ();
  PL_op = nextop; nextop = Perl_pp_print (aTHX);
  goto op_34432192;
op_34432192: /* leavesub */
  PERL_ASYNC_CHECK ();
  return nextop;
op_0:
  return 0;
}