=slide Data types

<p><img src="../svtypes.png">

<hr><xmp>
int  SvTYPE(SV* sv);
void SvUPGRADE(SV* sv, int type);
</xmp>

=slide SvNULL

<p><img src="../svhead.png">

<p><img src="../flags.png">

<hr><xmp>
SV* NEWSV(int tag, STRLEN len);
SV* newSVsv(SV*);

int SvOK(SV*);
int SvOK_off(SV*);
int SvIOK(SV*);
int SvNOK(SV*);
int SvPOK(SV*);
int SvROK(SV*);
int SvNIOK(SV*);            (SVp_?OK >> PRIVSHIFT) == SVf_?OK

int SvMAGICAL(SV*);
int SvGMAGICAL(SV*);
int SvSMAGICAL(SV*);
int SvRMAGICAL(SV*);
</xmp>

=slide SvRV

<p><img src="../svrv.png">

<hr><xmp>
SV* newRV_inc((SV*) thing);
SV* newRV_noinc((SV*) thing);

U32 SvROK(SV*)      Has a valid reference pointer?
SV* SvRV(SV*)
void SvROK_on(SV*)  Tells an SV that it is an RV.
void SvROK_off(SV*) Unsets the RV status of an SV.

int SvREFCNT(SV* sv);
SV* SvREFCNT_inc(SV* sv);
void SvREFCNT_dec(SV* sv);
</xmp>

=slide SvIV and SvNV

<p><img src="../sviv.png">

<p><img src="../svnv.png">

<hr><xmp>
SV*  newSViv(IV);
SV*  newSVnv(double);
</xmp>

=slide SvPV

<p><img src="../svpv.png">

<hr><xmp>
SV*   newSVpv(char*, int);
SV*   newSVpvn(char*, int);
SV*   newSVpvf(const char*, ...);

char* SvPV(SV*, STRLEN len); /* macro */
char* SvPV_force(SV*, STRLEN len);
char* SvPVX(SV*);

int SvCUR(SV*);
SvCUR_set(SV*, I32 val);
char* SvEND(SV*);
char* SvGROW(SV*, STRLEN newlen);

void  sv_catpv(SV*, char*);
void  sv_catpvn(SV*, char*, int);
void  sv_catpvf(SV*, const char*, ...);
void  sv_catpvfn(SV*, const char*, STRLEN,
                 va_list *, SV **, I32, bool);
void  sv_catsv(SV*, SV*);
</xmp>

=slide SvPVIV and SvPVNV

<p><img src="../svpviv.png">

<p><img src="../svpvnv.png">

<hr><xmp>
void  sv_setiv(SV*, IV);
void  sv_setuv(SV*, UV);
void  sv_setnv(SV*, double);
void  sv_setpv(SV*, char*);
void  sv_setpvn(SV*, char*, int)
void  sv_setpvf(SV*, const char*, ...);
void  sv_setpvfn(SV*, const char*, STRLEN,
                 va_list *, SV **, I32, bool);
void  sv_setsv(SV*, SV*);

SvPOK_on(SV*)
SvIOK_on(SV*)
SvIV(SV*)
SvNV(SV*)
SvTRUE(SV*)
</xmp>

=slide OOK

<p><img src="../ook.png">

<hr><xmp>
void sv_insert(SV* bigstr, STRLEN offset, STRLEN len,
              char *little, STRLEN littlelen);
void sv_chop(SV*, char* ptr);
void SvOOK_off(SV*);
</xmp>

=slide SvPVMG

<p><img src="../svpvmg.png">

<hr><xmp>
void   sv_magic(SV* sv, SV* obj, int how,
                char* name, I32 namlen);
void   sv_unmagic(SV* sv, int type);
MAGIC* mg_find(SV* sv, int type);

SV*    sv_bless(SV* sv, HV* stash);
</xmp>

=slide p5rx (SvPVBM)

<p><img src="../svpvbm.png">

<hr><xmp>
void  fbm_compile(SV* sv, U32 flags);
char* fbm_instr(char* str, char* strend,
                SV* sv, U32 flags);
</xmp>

=slide SvPVLV

<p><img src="../svpvlv.png">

=slide AV

<p><img src="../av.png">

<hr><xmp>
AV*  newAV();
AV*  av_make(I32 num, SV **ptr);

void  av_push(AV*, SV*);
SV*   av_pop(AV*);
SV*   av_shift(AV*);
void  av_unshift(AV*, I32 num);
I32   av_len(AV*);
SV**  av_fetch(AV*, I32 key, I32 lval);
SV**  av_store(AV*, I32 key, SV* val);
void  av_clear(AV*);
void  av_undef(AV*);
void  av_extend(AV*, I32 key);
</xmp>

=slide HV

<p><img src="../hv.png">

<hr>
<p><img src="../strtab.png">

<hr><xmp>
HV*  newHV();

SV**  hv_store(HV*, char* key, U32 klen, SV* val, U32 hash);
SV**  hv_fetch(HV*, char* key, U32 klen, I32 lval);

bool  hv_exists(HV*, char* key, U32 klen);
SV*   hv_delete(HV*, char* key, U32 klen, I32 flags);

void  hv_clear(HV*);
void  hv_undef(HV*);

I32   hv_iterinit(HV*);
HE*   hv_iternext(HV*);
char* hv_iterkey(HE* entry, I32* retlen);
SV*   hv_iterval(HV*, HE* entry);
</xmp>

=slide GV

<p><img src="../gv.png">

=slide Stashes

<p><img src="../stash.png">

<hr><xmp>
SV* perl_get_sv(char* name, int create);
AV* perl_get_av(char* name, int create);
HV* perl_get_hv(char* name, int create);
CV* perl_get_cv(char* name, int create);

GV* gv_fetchpv(char* name, int create, int type);
</xmp>


=slide CV

<p><img src="../cv.png">

=slide PAD

<p><img src="../pad.png">

<xmp>
PAD_SV(po) = PL_curpad[po]    /* po: PADOFFSET i.e. targ */
</xmp>

=slide OpTypes

A Perl program/subroutine is represented internally by a syntax tree built from OP nodes. 
Perl 5.005 had 346 different OP-codes, Perl 5.11.2 has 365 OP-Codes, see opnames.h.
In Perl there are 12 different OP classes, that are related like the following 
class hierarchy diagram shows: 

<p><img src="../optypes.png">

=slide OP's

<p><img src="../op1.png">
<p><img src="../op2.png">

<p><img src="../opsamp2.png">

=slide SvPVFM

<p><img src="../svpvfm.png">

=slide IO

<p><img src="../io.png">

=slide Stacks + Scope

<p><img src="../scope.png">
<p><img src="../stack.png">

=slide Context + sub

<p><img src="../context.png">

<p>The context setup for a Perl or XS subroutine does at <b>entersub</b>:
<xmp>
	ENTER;
	PUSHBLOCK(cx, CXt_SUB, SP);
	PUSHSUB(cx);
	cx->blk_sub.retop = PL_op->op_next;
	CvDEPTH(cv)++;
	SAVECOMPPAD();
	PAD_SET_CUR_NOSAVE(CvPADLIST(cv), CvDEPTH(cv));
        /* push args */
        /* call sub */
</xmp>
and at <b>leavesub</b>
<xmp>
        /* pop return value(s) */
	POPBLOCK(cx,newpm);
	LEAVE;
	cxstack_ix--;
    	POPSUB(cx,sv);	        /* release CV and @_ ... */
    	PL_curpm = newpm;	/* ... and pop $1 et al */
	LEAVESUB(sv);
    	return cx->blk_sub.retop;
</xmp>

=slide eval

<p><img src="../eval.png">

<p>Pack the op sequence into a simple try/catch switch between <code>JMPENV_PUSH</code> and
<code>JMPENV_POP</code> calls.

<p>The <b>struct jmpenv</b> packages the state required to perform a proper non-local jump, 
<b>top_env</b> being the initial JMPENV record. In case of abnormal exceptions 
(i.e. die) a <code>JMPENV_JUMP</code> must be done, a non-local jump out to 
the previous JMPENV level with a proper <em>setjmp</em> record.
