{
    "content": [
        {
            "type": "text",
            "text": "# perlclassguts (man)\n\n## NAME\n\nperlclassguts - Internals of how \"feature 'class'\" and class syntax works\n\n## DESCRIPTION\n\nThis document provides in-depth information about the way in which the perl interpreter\nimplements the \"feature 'class'\" syntax and overall behaviour.  It is not intended as an end-\nuser guide on how to use the feature. For that, see perlclass.\n\n## Sections\n\n- **NAME**\n- **DESCRIPTION**\n- **DATA STORAGE** (4 subsections)\n- **API** (4 subsections)\n- **OPCODES**\n- **COMPILE-TIME BEHAVIOUR** (3 subsections)\n- **RUNTIME BEHAVIOUR** (2 subsections)\n- **AUTHORS**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "perlclassguts",
        "section": "",
        "mode": "man",
        "summary": "perlclassguts - Internals of how \"feature 'class'\" and class syntax works",
        "synopsis": null,
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 7,
                "subsections": []
            },
            {
                "name": "DATA STORAGE",
                "lines": 1,
                "subsections": [
                    {
                        "name": "Classes",
                        "lines": 47
                    },
                    {
                        "name": "Fields",
                        "lines": 39
                    },
                    {
                        "name": "Methods",
                        "lines": 12
                    },
                    {
                        "name": "Instances",
                        "lines": 16
                    }
                ]
            },
            {
                "name": "API",
                "lines": 2,
                "subsections": [
                    {
                        "name": "Class Manipulation",
                        "lines": 35
                    },
                    {
                        "name": "Field Manipulation",
                        "lines": 24
                    },
                    {
                        "name": "Method Manipulation",
                        "lines": 16
                    },
                    {
                        "name": "Object Instances",
                        "lines": 21
                    }
                ]
            },
            {
                "name": "OPCODES",
                "lines": 29,
                "subsections": []
            },
            {
                "name": "COMPILE-TIME BEHAVIOUR",
                "lines": 1,
                "subsections": [
                    {
                        "name": "\"ADJUST\" Phasers",
                        "lines": 9
                    },
                    {
                        "name": "Attributes",
                        "lines": 10
                    },
                    {
                        "name": "Field Initializing Expressions",
                        "lines": 5
                    }
                ]
            },
            {
                "name": "RUNTIME BEHAVIOUR",
                "lines": 1,
                "subsections": [
                    {
                        "name": "Constructor",
                        "lines": 18
                    },
                    {
                        "name": "$self Access During Methods",
                        "lines": 10
                    }
                ]
            },
            {
                "name": "AUTHORS",
                "lines": 3,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "perlclassguts - Internals of how \"feature 'class'\" and class syntax works\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "This document provides in-depth information about the way in which the perl interpreter\nimplements the \"feature 'class'\" syntax and overall behaviour.  It is not intended as an end-\nuser guide on how to use the feature. For that, see perlclass.\n\nThe reader is assumed to be generally familiar with the perl interpreter internals overall.\nFor a more general overview of these details, see also perlguts.\n",
                "subsections": []
            },
            "DATA STORAGE": {
                "content": "",
                "subsections": [
                    {
                        "name": "Classes",
                        "content": "A class is fundamentally a package, and exists in the symbol table as an HV with an aux\nstructure in exactly the same way as a non-class package. It is distinguished from a non-\nclass package by the fact that the HvSTASHISCLASS() macro will return true on it.\n\nExtra information relating to it being a class is stored in the \"struct xpvhvaux\" structure\nattached to the stash, in the following fields:\n\nHV          *xhvclasssuperclass;\nCV          *xhvclassinitfieldscv;\nAV          *xhvclassadjustblocks;\nPADNAMELIST *xhvclassfields;\nPADOFFSET    xhvclassnextfieldix;\nHV          *xhvclassparammap;\n\n•   \"xhvclasssuperclass\"  will  be  \"NULL\"  for  a  class with no superclass. It will point\ndirectly to the stash of the parent class if one has  been  set  with  the  :isa()  class\nattribute.\n\n•   \"xhvclassinitfieldscv\"  will  contain a \"CV *\" pointing to a function to be invoked as\npart of the constructor of this class or any subclass thereof. This CV is responsible for\ninitializing all the fields defined by this class for a new instance. This CV will be  an\nanonymous  real  function - i.e. while it has no name and no GV, it is not a protosub and\nmay be directly invoked.\n\n•   \"xhvclassadjustblocks\" may point to an AV  containing  CV  pointers  to  each  of  the\n\"ADJUST\"  blocks  defined  on  the  class. If the class has a superclass, this array will\nadditionally contain duplicate pointers of the CVs of its parent class. The AV is created\nlazily the first time an element is pushed to it; it is valid for there not  to  be  one,\nand this pointer will be \"NULL\" in that case.\n\nThe CVs are stored directly, not via RVs. Each CV will be an anonymous real function.\n\n•   \"xhvclassfields\"  will  point  to a \"PADNAMELIST\" containing \"PADNAME\"s, each being one\ndefined field of the class. They are stored in order of declaration. Note  however,  that\nthe  index  into this array will not necessarily be equal to the \"fieldix\" of each field,\nbecause in the case of a subclass, the array will begin at zero  but  the  index  of  the\nfirst field in it will be non-zero if its parent class contains any fields at all.\n\nFor more information on how individual fields are represented, see \"Fields\".\n\n•   \"xhvclassnextfieldix\" gives the field index that will be assigned to the next field to\nbe added to the class. It is only useful at compile-time.\n\n•   \"xhvclassparammap\" may point to an HV which maps field \":param\" attribute names to the\nfield index of the field with that name. This mapping is copied from parent classes; each\nclass will contain the sum total of all its parents in addition to its own.\n"
                    },
                    {
                        "name": "Fields",
                        "content": "A  field  is  still  fundamentally  a lexical variable declared in a scope, and exists in the\n\"PADNAMELIST\" of its corresponding CV. Methods and other method-like CVs  can  still  capture\nthem  exactly as they can with regular lexicals. A field is distinguished from other kinds of\npad entry in that the PadnameIsFIELD() macro will return true on it.\n\nExtra information relating to  it  being  a  field  is  stored  in  an  additional  structure\naccessible  via the PadnameFIELDINFO() macro on the padname. This structure has the following\nfields:\n\nPADOFFSET  fieldix;\nHV        *fieldstash;\nOP        *defop;\nSV        *paramname;\nbool       defifundef;\nbool       defiffalse;\n\n•   \"fieldix\" stores the \"field index\" of the field; that is, the  index  into  the  instance\nfield  array  where  this  field's value will be stored. Note that the first index in the\narray is not specially reserved. The first field in a class will start from  field  index\n0.\n\n•   \"fieldstash\"  stores a pointer to the stash of the class that defined this field. This is\nnecessary in case there are multiple classes defined within the same scope; it is used to\ndisambiguate the fields of each.\n\n{\nclass C1; field $x;\nclass C2; field $x;\n}\n\n•   \"defop\" may store a pointer to a defaulting expression optree for this field.  Defaulting\nexpressions are optional; this field may be \"NULL\".\n\n•   \"paramname\" may point to a regular string SV containing the \":param\" name attribute given\nto the field. If none, it will be \"NULL\".\n\n•   One of \"defifundef\" and \"defiffalse\" will be true if the  defaulting  expression  was\nset using the \"//=\" or \"||=\" operators respectively.\n"
                    },
                    {
                        "name": "Methods",
                        "content": "A method is still fundamentally a CV, and has the same basic representation as one. It has an\noptree  and  a  pad,  and  is  stored  via a GV in the stash of its containing package. It is\ndistinguished from a non-method CV by the fact that the CvIsMETHOD() macro will  return  true\non it.\n\n(Note:  This macro should not be confused with the one that was previously called CvMETHOD().\nThat one does not relate to the class system, and  was  renamed  to  CvNOWARNAMBIGUOUS()  to\navoid this confusion.)\n\nThere  is  currently  no  extra information that needs to be stored about a method CV, so the\nstructure does not add any new fields.\n"
                    },
                    {
                        "name": "Instances",
                        "content": "Object instances are represented by an entirely new SV type, whose base type is  \"SVtPVOBJ\".\nThis  should  still  be blessed into its class stash and wrapped in an RV in the usual manner\nfor classical object.\n\nAs these are their own unique container type,  distinct  from  hashes  or  arrays,  the  core\n\"builtin::reftype\"  function  returns  a  new  value  when  asked  about these. That value is\n\"OBJECT\".\n\nInternally, such an object is an array of SV pointers whose size is fixed  at  creation  time\n(because  the  number  of  fields  in a class is known after compilation). An object instance\nstores the max field index within it (for basic error-checking on access), and  a  fixed-size\narray of SV pointers storing the individual field values.\n\nFields  of  array and hash type directly store AV or HV pointers into the array; they are not\nstored via an intervening RV.\n"
                    }
                ]
            },
            "API": {
                "content": "The data structures described above are supported by the following API functions.\n",
                "subsections": [
                    {
                        "name": "Class Manipulation",
                        "content": "classsetupstash\n\nvoid classsetupstash(HV *stash);\n\nCalled by the parser on encountering the \"class\" keyword. It upgrades the stash into being  a\nclass and prepares it for receiving class-specific items like methods and fields.\n\nclasssealstash\n\nvoid classsealstash(HV *stash);\n\nCalled by the parser at the end of a \"class\" block, or for unit classes its containing scope.\nThis  function performs various finalisation activities that are required before instances of\nthe class can be constructed, but could not have been done until all  the  information  about\nthe members of the class is known.\n\nAny  additions  to  or modifications of the class under compilation must be performed between\nthese two function calls. Classes cannot be modified once they have been sealed.\n\nclassaddfield\n\nvoid classaddfield(HV *stash, PADNAME *pn);\n\nCalled by pad.c as part of defining a new field name in the  current  pad.   Note  that  this\nfunction  does  not create the padname; that must already be done by pad.c. This API function\nsimply informs the class that the new field name has been created and is  now  available  for\nit.\n\nclassaddADJUST\n\nvoid classaddADJUST(HV *stash, CV *cv);\n\nCalled  by  the parser once it has parsed and constructed a CV for a new \"ADJUST\" block. This\ngets added to the list stored by the class.\n"
                    },
                    {
                        "name": "Field Manipulation",
                        "content": "classprepareinitfieldparse\n\nvoid classprepareinitfieldparse();\n\nCalled by the parser just before parsing an initializing expression  for  a  field  variable.\nThis  makes  use of a suspended compcv to combine all the field initializing expressions into\nthe same CV.\n\nclasssetfielddefop\n\nvoid classsetfielddefop(PADNAME *pn, OPCODE defmode, OP *defop);\n\nCalled by the parser after it has parsed an initializing expression for the field.  Sets  the\ndefaulting  expression  and  mode  of application. \"defmode\" should either be zero, or one of\n\"OPORASSIGN\" or \"OPDORASSIGN\" depending on the defaulting mode.\n\npadaddFIELD\n\n#define padaddFIELD\n\nThis flag constant tells the \"padaddname*\" family of functions that the new name should be\nadded  as  a  field.  There  is  no  need  to  call  classaddfield();  this  will  be  done\nautomatically.\n"
                    },
                    {
                        "name": "Method Manipulation",
                        "content": "classpreparemethodparse\n\nvoid classpreparemethodparse(CV *cv);\n\nCalled  by the parser after startsubparse() but immediately before doing anything else. This\nprepares the \"PLcompcv\" for parsing a method; arranging for  the  \"CvIsMETHOD\"  test  to  be\ntrue, adding the $self lexical, and any other activities that may be required.\n\nclasswrapmethodbody\n\nOP *classwrapmethodbody(OP *o);\n\nCalled  by  the  parser  at  the  end of parsing a method body into an optree but just before\nwrapping it in the eventual CV. This function inserts extra ops into the optree to  make  the\nmethod work correctly.\n"
                    },
                    {
                        "name": "Object Instances",
                        "content": "SVtPVOBJ\n\n#define SVtPVOBJ\n\nAn SV type constant used for comparison with the SvTYPE() macro.\n\nObjectMAXFIELD\n\nSSizet ObjectMAXFIELD(sv);\n\nA  function-like  macro  that obtains the maximum valid field index that can be accessed from\nthe \"ObjectFIELDS\" array.\n\nObjectFIELDS\n\nSV ObjectFIELDS(sv);\n\nA function-like macro that obtains the fields array  directly  out  of  an  object  instance.\nFields  can  be  accessed by their field index, from 0 up to the maximum valid index given by\n\"ObjectMAXFIELD\".\n"
                    }
                ]
            },
            "OPCODES": {
                "content": "OPMETHSTART\nnewUNOPAUX(OPMETHSTART, ...);\n\nAn \"OPMETHSTART\" is an \"UNOPAUX\" which must be present at the start of a method CV in order\nto make it work properly. This is inserted  by  classwrapmethodbody(),  and  even  appears\nbefore any optree fragment associated with signature argument checking or extraction.\n\nThis  op is responsible for shifting the value of $self out of the arguments list and binding\nany field variables that the method requires access to into the  pad.  The  AUX  vector  will\ncontain details of the field/pad index pairings required.\n\nThis  op also performs sanity checking on the invocant value. It checks that it is definitely\nan object reference of a compatible class type. If not, an exception is thrown.\n\nIf the \"opprivate\" field includes the \"OPpINITFIELDS\"  flag,  this  indicates  that  the  op\nbegins the special \"xhvclassinitfieldscv\" CV. In this case it should additionally take the\nsecond  value  from the arguments list, which should be a plain HV pointer (directly, not via\nRV). and bind it to the second pad slot, where the generated optree will expect to find it.\n\nOPINITFIELD\nAn \"OPINITFIELD\" is only invoked as part of  the  \"xhvclassinitfieldscv\"  CV  during  the\nconstruction  phase of an instance. This is the time that the individual SVs that make up the\nmutable fields of the instance (including  AVs  and  HVs)  are  actually  assigned  into  the\n\"ObjectFIELDS\"  array.  The  \"OPpINITFIELDAV\"  and  \"OPpINITFIELDHV\" private flags indicate\nwhether it is creating an AV or HV; if neither is set then an SV is created.\n\nIf the op has the \"OPfSTACKED\" flag it expects to find an initializing value on  the  stack.\nFor SVs this is the topmost SV on the data stack. For AVs and HVs it expects a marked list.\n",
                "subsections": []
            },
            "COMPILE-TIME BEHAVIOUR": {
                "content": "",
                "subsections": [
                    {
                        "name": "\"ADJUST\" Phasers",
                        "content": "During compiletime, parsing of an \"ADJUST\" phaser is handled in a fundamentally different way\nto the existing perl phasers (\"BEGIN\", etc...)\n\nRather  than  taking  the  usual  route,  the  tokenizer recognises that the \"ADJUST\" keyword\nintroduces a phaser block. The parser then parses the body of this block similarly to how  it\nwould  parse  an  (anonymous)  method  body,  creating a CV that has no name GV. This is then\ninserted  directly  into  the  class  information  by  calling  \"classaddADJUST\",  entirely\nbypassing the symbol table.\n"
                    },
                    {
                        "name": "Attributes",
                        "content": "During  compilation,  attributes of both classes and fields are handled in a different way to\nexisting perl attributes on subroutines and lexical variables.\n\nThe parser still forms an \"OPLIST\" optree of \"OPCONST\" nodes, but these are passed  to  the\n\"classapplyattributes\"  or  \"classapplyfieldattributes\"  functions.  Rather than using a\nclass lookup for a method in  the  class  being  parsed,  a  fixed  internal  list  of  known\nattributes  is used to find functions to apply the attribute to the class or field. In future\nthis may support user-supplied extension attribute, though at present it only recognises ones\ndefined by the core itself.\n"
                    },
                    {
                        "name": "Field Initializing Expressions",
                        "content": "During compilation, the parser makes use of a suspended compcv when  parsing  the  defaulting\nexpression  for  a  field. All the expressions for all the fields in the class share the same\nsuspended compcv, which is then  compiled  up  into  the  same  internal  CV  called  by  the\nconstructor to initialize all the fields provided by that class.\n"
                    }
                ]
            },
            "RUNTIME BEHAVIOUR": {
                "content": "",
                "subsections": [
                    {
                        "name": "Constructor",
                        "content": "The  generated constructor for a class itself is an XSUB which performs three tasks in order:\nit creates the instance SV itself, invokes the field initializers, then  invokes  the  ADJUST\nblock  CVs.  The  constructor  for  any  class  is always the same basic shape, regardless of\nwhether the class has a superclass or not.\n\nThe field initializers are collected into  a  generated  optree-based  CV  called  the  field\ninitializer  CV.  This  is  the  CV  which  contains  all  the optree fragments for the field\ninitializing expressions. When invoked, the field initializer CV might make a chained call to\nthe superclass initializer if one  exists,  before  invoking  all  of  the  individual  field\ninitialization  ops.  The  field initializer CV is invoked with two items on the stack; being\nthe instance SV and a direct HV containing the constructor parameters. Note  carefully:  this\nHV is passed directly, not via an RV reference. This is permitted because both the caller and\nthe callee are directly generated code and not arbitrary pure-perl subroutines.\n\nThe  ADJUST  block  CVs  are  all  collected into a single flat list, merging all of the ones\ndefined by the superclass as well. They are all invoked in order, after the field initializer\nCV.\n"
                    },
                    {
                        "name": "$self Access During Methods",
                        "content": "When classpreparemethodparse() is called, it arranges that the pad of the new CV body will\nbegin with a lexical called $self. Because the pad should be freshly-created at  this  point,\nthis will have the pad index of 1.  The function checks this and aborts if that is not true.\n\nBecause of this fact, code within the body of a method or method-like CV can reliably use pad\nindex 1 to obtain the invocant reference. The \"OPINITFIELD\" opcode also relies on this fact.\n\nIn  similar  fashion,  during the \"xhvclassinitfieldscv\" the next pad slot is relied on to\nstore the constructor parameters HV, at pad index 2.\n"
                    }
                ]
            },
            "AUTHORS": {
                "content": "Paul Evans\n\nperl v5.38.2                                 2026-06-12                             PERLCLASSGUTS(1)",
                "subsections": []
            }
        }
    }
}