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 :). |
---|