| 1 | To make sub classing pmc from pir work correctly, I planned to make the following changes |
|---|
| 2 | to the parrot core. |
|---|
| 3 | |
|---|
| 4 | Here is a example to clarify things a little bit up. |
|---|
| 5 | If you create for example an oject which is sub classed from the exception pmc class in pir now you get the following structure. |
|---|
| 6 | You get a pmc which is a instance object in which there is a field "proxyš which points |
|---|
| 7 | to the pmc holding the object. Here is a description of the actual memory layout. |
|---|
| 8 | I could be not all information is complete or 100% correct. |
|---|
| 9 | pmc |
|---|
| 10 | flags |
|---|
| 11 | *vtable -> = interp->vtables[394] (example) |
|---|
| 12 | *data = Parrot_Object_attributes |
|---|
| 13 | _class -> to a pmcproxy pmc describing the pir subclass of exception pmc class = interp->vtables[394]->_classe (example) |
|---|
| 14 | _attrib_store = pmc |
|---|
| 15 | flags |
|---|
| 16 | *vtable -> vtable of resizeable pmc array = interp->vtables[enum_class_ResizablePMCArray] |
|---|
| 17 | *data = Parrot_ResizablePMCArray_attributes |
|---|
| 18 | size -> equal to the size of the amount of attributes in the object in this case = 13 fields + 1 for proxy |
|---|
| 19 | **pmc_array -> array of 14 pmc objects |
|---|
| 20 | [0] proxy = pmc |
|---|
| 21 | flags |
|---|
| 22 | *vtable -> to pmcproxy pmc describing the exception pmc class |
|---|
| 23 | *data |
|---|
| 24 | id = INTVAL |
|---|
| 25 | birthtime = FLOATVAL |
|---|
| 26 | etc |
|---|
| 27 | thrower = PMC* |
|---|
| 28 | *metadata |
|---|
| 29 | *_synchronize |
|---|
| 30 | *_next_for_GC |
|---|
| 31 | [1] id = pmc holding a boxed intval |
|---|
| 32 | [2] birthtime = pmc holding a boxed floatval |
|---|
| 33 | etc |
|---|
| 34 | [13] thrower = pmc |
|---|
| 35 | resize_threshold |
|---|
| 36 | *metadata |
|---|
| 37 | *_synchronize |
|---|
| 38 | *_next_for_GC |
|---|
| 39 | *metadata |
|---|
| 40 | *_synchronize |
|---|
| 41 | *_next_for_GC |
|---|
| 42 | |
|---|
| 43 | *Note that all attributes of the base pmc object are stored twice |
|---|
| 44 | |
|---|
| 45 | interp |
|---|
| 46 | ... |
|---|
| 47 | **vtables |
|---|
| 48 | [...] |
|---|
| 49 | [enum_class_ResizablePMCArray] |
|---|
| 50 | *_namespace -> [parrot] |
|---|
| 51 | base_type -> enum_class_ResizablePMCArray |
|---|
| 52 | *whoami -> String holding "ResizablePMCArray" |
|---|
| 53 | flags |
|---|
| 54 | *provides_str "scalar" |
|---|
| 55 | *isa_hash -> hash containing item "Exception" |
|---|
| 56 | *pmc_class = pmc |
|---|
| 57 | flags |
|---|
| 58 | vtable -> null or points to pmc of type pmcproxy describing the pmcproxy pmc class |
|---|
| 59 | *data |
|---|
| 60 | id -> = vtable->base_type |
|---|
| 61 | *name -> = vtable->whoami |
|---|
| 62 | *fullname |
|---|
| 63 | *_namespace -> = vtable->_namespace (at least should be) |
|---|
| 64 | instantiated -> 1 class is instantiated |
|---|
| 65 | *parents |
|---|
| 66 | *all_parents -> = vtable->mro |
|---|
| 67 | *roles -> provides same information as vtable->provides_str |
|---|
| 68 | *methods |
|---|
| 69 | *vtable_overrides |
|---|
| 70 | *attrib_metadata -> build from vtable->attribute_defs |
|---|
| 71 | *attrib_index |
|---|
| 72 | *attrib_cache |
|---|
| 73 | *resolve_method |
|---|
| 74 | *parent_overrides |
|---|
| 75 | *metadata |
|---|
| 76 | *_synchronize |
|---|
| 77 | *_next_for_GC |
|---|
| 78 | *mro -> pmc array holding parents |
|---|
| 79 | *attribute_defs -> "Iid Fbirthtime Smessage Fpayload etc " |
|---|
| 80 | *ro_variant_vtable -> vtable where only flags and functions are different rest is redundant |
|---|
| 81 | the list of functions |
|---|
| 82 | [...] |
|---|
| 83 | [394] |
|---|
| 84 | *_namespace -> [parrot;mypackage;myclass] |
|---|
| 85 | base_type -> 394 |
|---|
| 86 | *whoami -> String holding "myclass" |
|---|
| 87 | flags |
|---|
| 88 | *provides_str "scalar" (cloned from interp->vtables[enum_class_ResizablePMCArray]) |
|---|
| 89 | *isa_hash -> hash containing item "Exception" (cloned from interp->vtables[enum_class_ResizablePMCArray]) |
|---|
| 90 | *pmc_class = pmc |
|---|
| 91 | flags |
|---|
| 92 | vtable -> null or points to pmc of type pmcproxy describing the pmcproxy pmc class |
|---|
| 93 | *data |
|---|
| 94 | id -> = vtable->base_type |
|---|
| 95 | *name -> = vtable->whoami |
|---|
| 96 | *fullname |
|---|
| 97 | *_namespace -> = vtable->_namespace (at least should be) |
|---|
| 98 | instantiated -> 1 class is instantiated |
|---|
| 99 | *parents |
|---|
| 100 | *all_parents -> = vtable->mro |
|---|
| 101 | *roles -> provides same information as vtable->provides_str + extra added roles |
|---|
| 102 | *methods |
|---|
| 103 | *vtable_overrides |
|---|
| 104 | *attrib_metadata -> build from vtable->attribute_defs + extra added attributes |
|---|
| 105 | *attrib_index |
|---|
| 106 | *attrib_cache |
|---|
| 107 | *resolve_method |
|---|
| 108 | *parent_overrides |
|---|
| 109 | *metadata |
|---|
| 110 | *_synchronize |
|---|
| 111 | *_next_for_GC |
|---|
| 112 | *mro -> = this->pmc_class->all_parents |
|---|
| 113 | *attribute_defs -> "Iid Fbirthtime Smessage Fpayload etc " (cloned from interp->vtables[enum_class_ResizablePMCArray]) |
|---|
| 114 | *ro_variant_vtable -> vtable where only flags and functions are different rest is redundant a clone(from interp->vtables[enum_class_ResizablePMCArray]) |
|---|
| 115 | the list of functions -> cloned from interp->vtables[enum_class_ResizablePMCArray] |
|---|
| 116 | ... |
|---|
| 117 | |
|---|
| 118 | My plan is to do the following things |
|---|
| 119 | * Make all pmc an object |
|---|
| 120 | *Move all functionality from object.pmc to default.pmc |
|---|
| 121 | - Remove object.pmc |
|---|
| 122 | - Rename default.pmc to object.pmc |
|---|
| 123 | *Move the _attrib_store to the pmc struct |
|---|
| 124 | *Doing this by combining it into the *data field |
|---|
| 125 | -change the indexing mechanism of class.pmc |
|---|
| 126 | -DISCUSS! whether where are going to store (U)INTVAL and FLOATVAL as |
|---|
| 127 | primitive or as boxed items (see below) |
|---|
| 128 | *Remove all fields form vtable except the functions |
|---|
| 129 | *This will remove redundant fields in the system |
|---|
| 130 | *Add vtable and ro_vtable field to class.pmc |
|---|
| 131 | *replace interp->vtables by interp->classes |
|---|
| 132 | -bootstrap, loading/initing of the core pmc class object |
|---|
| 133 | -registering of new classes |
|---|
| 134 | *replace pmc->vtable by pmc->_class |
|---|
| 135 | *Remove the pmcproxy.pmc class |
|---|
| 136 | |
|---|
| 137 | This will result in the following things. |
|---|
| 138 | *all pmc items becoming object, without any extra memory usage, except for extra attributes in class.pmc |
|---|
| 139 | -so their attributes can be accessed via pir. |
|---|
| 140 | -We migth want to make an option to declare certain fields in a pmc as private. |
|---|
| 141 | * subclassing from pir works as expected |
|---|
| 142 | * typeof and related ops works as expected see tickets #879 #880 +more |
|---|
| 143 | * will solve several different tickets |
|---|
| 144 | * memory usage reduction (big one :) ) |
|---|
| 145 | * performance boost |
|---|
| 146 | |
|---|
| 147 | * the pmc structure will become |
|---|
| 148 | struct PMC { |
|---|
| 149 | Parrot_UInt flags; |
|---|
| 150 | PMC *_class; |
|---|
| 151 | DPOINTER *data; /* with different structure see xx*/ |
|---|
| 152 | PMC *_class; |
|---|
| 153 | PMC *_metadata; /* properties */ |
|---|
| 154 | struct _Sync *_synchronize; |
|---|
| 155 | PMC *_next_for_GC; /* other are busy removing this one */ |
|---|
| 156 | } |
|---|
| 157 | * interp->vtables replaced by interp->classes |
|---|
| 158 | * 2 added fields to class.pmc holding vtable and read only vtable |
|---|
| 159 | * added field to class.pmc to handle new indexing mechanism |
|---|
| 160 | * vtable struct will only contain the pointers to the functions |
|---|
| 161 | |
|---|
| 162 | The data structure will become an array of aligned items. For example I would |
|---|
| 163 | have the following items which is created in pir code by extending |
|---|
| 164 | the pmc class somepmcclass. |
|---|
| 165 | * INTVAL myint |
|---|
| 166 | * FLOAT myfloat |
|---|
| 167 | * DOUBLE mydouble |
|---|
| 168 | * PMC * aPMC |
|---|
| 169 | * PMC added by pir class this also is PMC* "addedpmc" |
|---|
| 170 | * DOUBLE added by pir class "addeddouble" |
|---|
| 171 | * FLOAT added by pir class "addedfloat" |
|---|
| 172 | If a would compile on a 32 bits i368 machine then |
|---|
| 173 | alignSize = 4 byte |
|---|
| 174 | INTVALSize = 4 byte |
|---|
| 175 | FLAOTSize = 4 byte |
|---|
| 176 | DOUBLESize = 8 byte |
|---|
| 177 | pointSize = 4 byte |
|---|
| 178 | So my index will be come |
|---|
| 179 | myInt = 0 |
|---|
| 180 | myfloat = 1 |
|---|
| 181 | mydouble = 2 |
|---|
| 182 | aPMC = 4 /* double uses to aligmentSizes */ |
|---|
| 183 | addedpmc = 5 |
|---|
| 184 | addeddouble = 6 |
|---|
| 185 | addedfloat = 8 |
|---|
| 186 | |
|---|
| 187 | The struct of this class for the code in pmc class will look in this |
|---|
| 188 | typedef struct Parrot_somepmcclass_attributes { |
|---|
| 189 | INTVAL myint; |
|---|
| 190 | FLOAT myfloat; |
|---|
| 191 | DOUBLE mydouble; |
|---|
| 192 | PMC * aPMC; |
|---|
| 193 | } Parrot_somepmcclass_attributes; |
|---|
| 194 | |
|---|
| 195 | The class.pmc will also get a extra field which tells on which indexes there are |
|---|
| 196 | pmc objects present, which is needed for the mark function. |
|---|
| 197 | In the example described above this will become. |
|---|
| 198 | int * = [4,5] |
|---|
| 199 | |
|---|
| 200 | Because my plan is to store all primitive as primitives as done now in pmc classes |
|---|
| 201 | I might get the following problem. |
|---|
| 202 | When I have a hll which does not use parrot boxed type but it own type, it will |
|---|
| 203 | get a parrot boxed type if does return from getattribe op. |
|---|
| 204 | But the same problem also happens with the box op. I do not know the details of this |
|---|
| 205 | but a hll could override these ops to solve this problem. |
|---|
| 206 | Ok we then have solved that problem. |
|---|
| 207 | The big question which leave my are there any hll which stores extra information onto |
|---|
| 208 | a integer,float or double which have to be preserved when doing set attribute and |
|---|
| 209 | after that doing a get attribute. |
|---|
| 210 | |
|---|
| 211 | Because this is a big change I made a plan for myself to implement this in phases. |
|---|
| 212 | Here is the list of phases I planned for this change. |
|---|
| 213 | * move object attribute store to pmc struct by adding extra field _pmc_array (done) |
|---|
| 214 | -storage does not have to be re-sizable because ones class is instantiated it can't add |
|---|
| 215 | or remove any properties to the class |
|---|
| 216 | * add interp->classes field and allocation stuff (done) |
|---|
| 217 | * add vtable and ro_vtable field in class.pmc (done) |
|---|
| 218 | * add bootstrap code to load interp->classes data (understanding of pmc2c.pl done, now to change it) |
|---|
| 219 | * add class registering code for interp->classes data |
|---|
| 220 | * replace interp->vtable[] code by interp->classes[]->vtable |
|---|
| 221 | * replace pmc->vtable by pmc->class |
|---|
| 222 | * make new indexing system |
|---|
| 223 | * merge newly created _pmc_array with data and remove _pmc_array again |
|---|
| 224 | * move functionality of object.pmc to default.pmc |
|---|
| 225 | * hope merging of vtable functions goes correctly that none of the important object acces vtable |
|---|
| 226 | function overlap with other vtable functions in other pmc objects |
|---|
| 227 | * removal of pmcproxy class |
|---|
| 228 | * removal of object.pmc |
|---|
| 229 | * rename default.pmc -> object.pmc |
|---|
| 230 | * remove any left references to the fields in vtable struct except the functions doh |
|---|
| 231 | * remove these fields |
|---|
| 232 | * cleanup of code, broken test etc, coding std |
|---|
| 233 | |
|---|
| 234 | Of course unexpected things can let me reshuffle this list. |
|---|
| 235 | |
|---|
| 236 | After the change the same memory layout as above will look like |
|---|
| 237 | pmc |
|---|
| 238 | flags |
|---|
| 239 | *_class -> = interp->classes[394] (example) |
|---|
| 240 | *data |
|---|
| 241 | [0] id = INTVAL |
|---|
| 242 | [1] birthtime = FLOATVAL |
|---|
| 243 | etc |
|---|
| 244 | [12] thrower = pmc* |
|---|
| 245 | *metadata |
|---|
| 246 | *_synchronize |
|---|
| 247 | *_next_for_GC |
|---|
| 248 | |
|---|
| 249 | *Note that in this case there is no DOUBLEVAl present other wise that one would take up 2 indexes |
|---|
| 250 | |
|---|
| 251 | interp |
|---|
| 252 | ... |
|---|
| 253 | **classes |
|---|
| 254 | [...] |
|---|
| 255 | [394] |
|---|
| 256 | flags |
|---|
| 257 | _class = pmc object |
|---|
| 258 | flags |
|---|
| 259 | _class -> = interp->classes[enum_class_Class] points to the class describing the class.pmc |
|---|
| 260 | *data |
|---|
| 261 | id -> = 394 |
|---|
| 262 | *name -> = "myclass" |
|---|
| 263 | *fullname |
|---|
| 264 | *_namespace -> = [parrot;mypackage;myclass] |
|---|
| 265 | instantiated -> 1 class is instantiated |
|---|
| 266 | *parents |
|---|
| 267 | *all_parents |
|---|
| 268 | *roles |
|---|
| 269 | *methods |
|---|
| 270 | *vtable_overrides |
|---|
| 271 | *attrib_metadata |
|---|
| 272 | *attrib_index -> index using new indexing mechanism |
|---|
| 273 | *attrib_cache |
|---|
| 274 | *resolve_method |
|---|
| 275 | *parent_overrides |
|---|
| 276 | *vtable -> vtable holding only function pointers (initialily cloned from pmc base obect) |
|---|
| 277 | *ro_vtable -> vtable holding only function pointers (initialily cloned from pmc base obect) |
|---|
| 278 | *is_pmc_index -> telling which attributes in the pmc->data are pmc (pobj*) objects |
|---|
| 279 | *metadata |
|---|
| 280 | *_synchronize |
|---|
| 281 | *_next_for_GC |
|---|
| 282 | |
|---|
| 283 | Because it is a big change, it would be fine to have separate branch for this. |
|---|
| 284 | If you guys accept my plan :). |
|---|