=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.