Layout_builders: introduce posets for better performances
[nit.git] / src / layout_builders.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Table layout builders
16 # Tables are used to implement objects mecanisms like:
17 # * message sending
18 # * attribute accessing
19 # * typing
20 # * resolution (for generic types)
21 # This module provides various layout for object tables:
22 # * coloring
23 # * binary matrix
24 # * perfect hashing (and & mod operators)
25 module layout_builders
26
27 import abstract_compiler
28
29 # Layouts
30
31 # A layout is the result of computation by builders
32 # it contains necessary informations for basic table creation
33 class Layout[E: Object]
34 # Ids or each element
35 var ids: Map[E, Int] = new HashMap[E, Int]
36 # Fixed positions of each element in all tables
37 var pos: Map[E, Int] = new HashMap[E, Int]
38 end
39
40 # A PHLayout is used everywere the builder used perfect hashing
41 # it adds masks and hashes informations to std layout
42 class PHLayout[HOLDER: Object, E: Object]
43 super Layout[E]
44 # Masks used by hash function
45 var masks: Map[HOLDER, Int] = new HashMap[HOLDER, Int]
46 # Positions of each element for each tables
47 var hashes: Map[HOLDER, Map[E, Int]] = new HashMap[HOLDER, Map[E, Int]]
48 end
49
50 # Builders
51
52 # TypingLayoutBuilder is used to build a layout for typing tables (by type or by class)
53 interface TypingLayoutBuilder[E: Object]
54 # Build typing table layout
55 # elements: the set of elements (classes or types) used in typing tables
56 fun build_layout(elements: Set[E]): Layout[E] is abstract
57 # Get the poset used for table layout construction
58 # REQUIRE: build_layout
59 fun poset: nullable POSet[E] is abstract
60 end
61
62 # Layout builder dedicated to vft, attribute & VT tables
63 interface PropertyLayoutBuilder[E: MProperty]
64 # Build table layout for attributes, methods and virtual types
65 # elements: the set of classes containing the properties to use in table layout
66 fun build_layout(elements: Set[MClass]): Layout[E] is abstract
67 end
68
69 # For resolution tables (generics)
70 interface ResolutionLayoutBuilder
71 # Build resolution table layout
72 # elements: association between classes and resolved types
73 fun build_layout(elements: Map[MClassType, Set[MType]]): Layout[MType] is abstract
74 end
75
76 # POSet builders
77
78 # A POSet builder build a poset for a set of MType or MClass
79 # the resulting poset is used by the layout builders
80 private abstract class POSetBuilder[E: Object]
81 private var mmodule: MModule
82 init(mmodule: MModule) do self.mmodule = mmodule
83 # Build the poset from `elements`
84 private fun build_poset(elements: Set[E]): POSet[E] is abstract
85 end
86
87 # A TypingLayoutBuilder used for MType based typing
88 # such as in separate compilers
89 private class MTypePOSetBuilder
90 super POSetBuilder[MType]
91 redef fun build_poset(elements) do
92 var poset = new POSet[MType]
93 for e in elements do
94 poset.add_node(e)
95 for o in elements do
96 if e == o then continue
97 if e.is_subtype(mmodule, null, o) then
98 poset.add_edge(e, o)
99 end
100 end
101 end
102 return poset
103 end
104 end
105
106 # A TypingLayoutBuilder used for MClass based typing
107 # such as in erased compilers or used in property coloring
108 private class MClassPOSetBuilder
109 super POSetBuilder[MClass]
110 redef fun build_poset(elements) do return mmodule.flatten_mclass_hierarchy
111 end
112
113 # Matrice computers
114
115 # Abstract layout builder for resolution tables using Binary Matrix (BM)
116 abstract class TypingBMizer[E: Object]
117 super TypingLayoutBuilder[E]
118
119 private var mmodule: MModule
120 private var poset_builder: POSetBuilder[E]
121 private var poset_cache: nullable POSet[E]
122
123 private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
124 self.mmodule = mmodule
125 self.poset_builder = poset_builder
126 end
127
128 redef fun poset do return poset_cache
129
130 # Compute mtypes ids and position using BM
131 redef fun build_layout(elements: Set[E]): Layout[E] do
132 var result = new Layout[E]
133 var ids = new HashMap[E, Int]
134 poset_cache = poset_builder.build_poset(elements)
135 var lin = poset.to_a
136 poset.sort(lin)
137 for element in lin do
138 ids[element] = ids.length
139 end
140 result.ids = ids
141 result.pos = ids
142 return result
143 end
144 end
145
146 # Layout builder for typing tables based on classes using Binary Matrix (BM)
147 class MTypeBMizer
148 super TypingBMizer[MType]
149 init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
150 end
151
152 # Layout builder for typing tables based on types using Binary Matrix (BM)
153 class MClassBMizer
154 super TypingBMizer[MClass]
155 init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
156 end
157
158 # Layout builder for resolution tables using Binary Matrix (BM)
159 class ResolutionBMizer
160 super ResolutionLayoutBuilder
161
162 init do end
163
164 redef fun build_layout(elements) do
165 var result = new Layout[MType]
166 var ids = new HashMap[MType, Int]
167 var color = 0
168 for mclasstype, mclasstypes in elements do
169 for element in mclasstypes do
170 if ids.has_key(element) then continue
171 ids[element] = color
172 color += 1
173 end
174 end
175 result.ids = ids
176 result.pos = ids
177 return result
178 end
179 end
180
181 # Abstract Layout builder for mproperties using Binary Matrix (BM)
182 abstract class MPropertyBMizer[E: MProperty]
183 super PropertyLayoutBuilder[E]
184
185 type MPROP: MProperty
186
187 var mmodule: MModule
188
189 init(mmodule: MModule) do self.mmodule = mmodule
190
191 redef fun build_layout(elements) do
192 var result = new Layout[E]
193 var ids = new HashMap[E, Int]
194 var lin = new Array[MClass]
195 lin.add_all(elements)
196 self.mmodule.linearize_mclasses(lin)
197 for mclass in lin do
198 for mproperty in properties(mclass) do
199 if ids.has_key(mproperty) then continue
200 ids[mproperty] = ids.length
201 end
202 end
203 result.pos = ids
204 return result
205 end
206
207 # extract properties of a mclass
208 private fun properties(mclass: MClass): Set[E] do
209 var properties = new HashSet[E]
210 for mprop in self.mmodule.properties(mclass) do
211 if mprop isa MPROP then properties.add(mprop)
212 end
213 return properties
214 end
215 end
216
217 # Layout builder for vft using Binary Matrix (BM)
218 class MMethodBMizer
219 super MPropertyBMizer[MMethod]
220 redef type MPROP: MMethod
221 init(mmodule: MModule) do super(mmodule)
222 end
223
224 # Layout builder for attribute tables using Binary Matrix (BM)
225 class MAttributeBMizer
226 super MPropertyBMizer[MAttribute]
227 redef type MPROP: MAttribute
228 init(mmodule: MModule) do super(mmodule)
229 end
230
231 # BMizing for MVirtualTypeProps
232 class MVirtualTypePropBMizer
233 super MPropertyBMizer[MVirtualTypeProp]
234 redef type MPROP: MVirtualTypeProp
235 init(mmodule: MModule) do super(mmodule)
236 end
237
238 # Colorers
239
240 # Abstract Layout builder for typing table using coloration (CL)
241 abstract class TypingColorer[E: Object]
242 super TypingLayoutBuilder[E]
243
244 private var core: Set[E] = new HashSet[E]
245 private var crown: Set[E] = new HashSet[E]
246 private var border: Set[E] = new HashSet[E]
247 private var coloration_result: Map[E, Int] = new HashMap[E, Int]
248
249 private var mmodule: MModule
250 private var poset_builder: POSetBuilder[E]
251 private var poset_cache: nullable POSet[E]
252
253 private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
254 self.mmodule = mmodule
255 self.poset_builder = poset_builder
256 end
257
258 redef fun poset do return poset_cache
259
260 # Compute the layout with coloring
261 redef fun build_layout(elements: Set[E]): Layout[E] do
262 poset_cache = poset_builder.build_poset(elements)
263 var result = new Layout[E]
264 result.ids = compute_ids(elements)
265 result.pos = colorize(elements)
266 return result
267 end
268
269 private fun compute_ids(elements: Set[E]): Map[E, Int] do
270 var ids = new HashMap[E, Int]
271 for element in reverse_linearize(elements) do
272 ids[element] = ids.length
273 end
274 return ids
275 end
276
277 private fun colorize(elements: Set[E]): Map[E, Int] do
278 tag_elements(elements)
279 build_conflicts_graph
280 colorize_elements(core)
281 colorize_elements(border)
282 colorize_elements(crown)
283 return coloration_result
284 end
285
286 # Colorize a collection of elements
287 private fun colorize_elements(elements: Set[E]) do
288 var min_color = 0
289
290 var lin = reverse_linearize(elements)
291 for element in lin do
292 var color = min_color
293 while not self.is_color_free(element, elements, color) do
294 color += 1
295 end
296 coloration_result[element] = color
297 color = min_color
298 end
299 end
300
301 # Check if a related element to the element already use the color
302 private fun is_color_free(element: E, elements: Set[E], color: Int): Bool do
303 if conflicts_graph.has_key(element) then
304 for st in conflicts_graph[element] do
305 if coloration_result.has_key(st) and coloration_result[st] == color then return false
306 end
307 end
308 for st in self.poset[element].greaters do
309 if st == element then continue
310 if coloration_result.has_key(st) and coloration_result[st] == color then return false
311 end
312 return true
313 end
314
315 # Tag elements as core, crown or border
316 private fun tag_elements(elements: Set[E]) do
317 for element in elements do
318 # Check if sub elements are all in single inheritance
319 var all_subelements_si = true
320 for subelem in self.poset[element].smallers do
321 if self.poset[subelem].direct_greaters.length > 1 then
322 all_subelements_si = false
323 break
324 end
325 end
326
327 # Tag as core, crown or border
328 if self.poset[element].direct_greaters.length > 1 then
329 core.add_all(self.poset[element].greaters)
330 if all_subelements_si then
331 border.add(element)
332 end
333 else if not all_subelements_si then
334 core.add_all(self.poset[element].greaters)
335 else
336 crown.add(element)
337 end
338 end
339 end
340
341 # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
342 private fun build_conflicts_graph do
343 self.conflicts_graph = new HashMap[E, HashSet[E]]
344 var core = reverse_linearize(self.core)
345 for t in core do
346 for i in self.linear_extension(t) do
347 if t == i then continue
348
349 var lin_i = self.linear_extension(i)
350
351 for j in self.linear_extension(t) do
352 if i == j or j == t then continue
353 var lin_j = self.linear_extension(j)
354
355 var d_ij = lin_i - lin_j
356 var d_ji = lin_j - lin_i
357
358 for ed1 in d_ij do
359 if not conflicts_graph.has_key(ed1) then conflicts_graph[ed1] = new HashSet[E]
360 # add ed1 x ed2 to conflicts graph
361 for ed2 in d_ji do conflicts_graph[ed1].add(ed2)
362 end
363 for ed1 in d_ij do
364 if not conflicts_graph.has_key(ed1) then conflicts_graph[ed1] = new HashSet[E]
365 # add ed1 x ed2 to conflicts graph
366 for ed2 in d_ji do conflicts_graph[ed1].add(ed2)
367 end
368 end
369 end
370 end
371 end
372
373 private var conflicts_graph: nullable HashMap[E, Set[E]]
374
375 # cache for linear_extensions
376 private var linear_extensions_cache: Map[E, Array[E]] = new HashMap[E, Array[E]]
377
378 # Return a linear_extension of super_elements of the element
379 private fun linear_extension(element: E): Array[E] do
380 if not self.linear_extensions_cache.has_key(element) then
381 var supers = new HashSet[E]
382 supers.add_all(self.poset[element].greaters)
383 self.linear_extensions_cache[element] = self.linearize(supers)
384 end
385 return self.linear_extensions_cache[element]
386 end
387
388 private fun reverse_linearize(elements: Set[E]): Array[E] do
389 var lin = new Array[E]
390 lin.add_all(elements)
391 poset.sort(lin)
392 return lin
393 end
394 private fun linearize(elements: Set[E]): Array[E] do return reverse_linearize(elements).reversed
395 end
396
397 # Layout builder for typing tables based on types using coloration (CL)
398 class MTypeColorer
399 super TypingColorer[MType]
400 init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
401 end
402
403 # Layout builder for typing tables based on classes using coloration (CL)
404 class MClassColorer
405 super TypingColorer[MClass]
406 init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
407 end
408
409 # Abstract Layout builder for properties tables using coloration (CL)
410 abstract class MPropertyColorer[E: MProperty]
411 super PropertyLayoutBuilder[E]
412
413 type MPROP: MProperty
414
415 private var mmodule: MModule
416 private var class_colorer: MClassColorer
417 private var coloration_result: Map[E, Int] = new HashMap[E, Int]
418
419 init(mmodule: MModule, class_colorer: MClassColorer) do
420 self.mmodule = mmodule
421 self.class_colorer = class_colorer
422 end
423
424 # Compute mclasses ids and position using BM
425 redef fun build_layout(mclasses: Set[MClass]): Layout[E] do
426 var result = new Layout[E]
427 result.pos = self.colorize(mclasses)
428 return result
429 end
430
431 private fun colorize(mclasses: Set[MClass]): Map[E, Int] do
432 self.colorize_core(self.class_colorer.core)
433 self.colorize_crown(self.class_colorer.crown)
434 return self.coloration_result
435 end
436
437 # Colorize properties of the core hierarchy
438 private fun colorize_core(mclasses: Set[MClass]) do
439 var min_color = 0
440 for mclass in mclasses do
441 var color = min_color
442 # check last color used by parents
443 color = max_color(color, mclass.in_hierarchy(mmodule).direct_greaters)
444 # check max color used in conflicts
445 if self.class_colorer.conflicts_graph.has_key(mclass) then
446 color = max_color(color, self.class_colorer.conflicts_graph[mclass])
447 end
448 colorize_elements(self.properties(mclass), color)
449 end
450 end
451
452 # Colorize properties of the crown hierarchy
453 private fun colorize_crown(mclasses: Set[MClass]) do
454 for mclass in mclasses do
455 var parents = new HashSet[MClass]
456 if mmodule.flatten_mclass_hierarchy.has(mclass) then
457 parents.add_all(mclass.in_hierarchy(mmodule).direct_greaters)
458 end
459 colorize_elements(self.properties(mclass), max_color(0, parents))
460 end
461 end
462
463 # Colorize a collection of mproperties given a starting color
464 private fun colorize_elements(elements: Collection[E], start_color: Int) do
465 for element in elements do
466 if self.coloration_result.has_key(element) then continue
467 self.coloration_result[element] = start_color
468 start_color += 1
469 end
470 end
471
472 private fun max_color(min_color: Int, mclasses: Collection[MClass]): Int do
473 var max_color = min_color
474
475 for mclass in mclasses do
476 for mproperty in self.properties(mclass) do
477 var color = min_color
478 if self.coloration_result.has_key(mproperty) then
479 color = self.coloration_result[mproperty]
480 if color >= max_color then max_color = color + 1
481 end
482 end
483 end
484 return max_color
485 end
486
487 # Filter properties
488 private fun properties(mclass: MClass): Set[E] do
489 var properties = new HashSet[E]
490 for mprop in self.mmodule.properties(mclass) do
491 if mprop isa MPROP then properties.add(mprop)
492 end
493 return properties
494 end
495 end
496
497 # Layout builder for vft using coloration (CL)
498 class MMethodColorer
499 super MPropertyColorer[MMethod]
500
501 redef type MPROP: MMethod
502 init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
503 end
504
505 # Layout builder for attributes using coloration (CL)
506 class MAttributeColorer
507 super MPropertyColorer[MAttribute]
508
509 redef type MPROP: MAttribute
510 init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
511 end
512
513 # Layout builder for virtual types using coloration (CL)
514 class MVirtualTypePropColorer
515 super MPropertyColorer[MVirtualTypeProp]
516
517 redef type MPROP: MVirtualTypeProp
518 init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
519 end
520
521 # Layout builder for resolution tables using coloration (CL)
522 class ResolutionColorer
523 super ResolutionLayoutBuilder
524
525 private var coloration_result: Map[MType, Int] = new HashMap[MType, Int]
526
527 init do end
528
529 # Compute resolved types colors
530 redef fun build_layout(elements) do
531 self.build_conflicts_graph(elements)
532 var result = new Layout[MType]
533 result.ids = self.compute_ids(elements)
534 result.pos = self.colorize_elements(elements)
535 return result
536 end
537
538 private fun compute_ids(elements: Map[MClassType, Set[MType]]): Map[MType, Int] do
539 var ids = new HashMap[MType, Int]
540 var color = 0
541 for mclasstype, mclasstypes in elements do
542 for element in mclasstypes do
543 if ids.has_key(element) then continue
544 ids[element] = color
545 color += 1
546 end
547 end
548 return ids
549 end
550
551 # Colorize a collection of elements
552 private fun colorize_elements(elements: Map[MClassType, Set[MType]]): Map[MType, Int] do
553 var min_color = 0
554 for mclasstype, mclasstypes in elements do
555 for element in mclasstypes do
556 if self.coloration_result.has_key(element) then continue
557 var color = min_color
558 while not self.is_color_free(element, color) do
559 color += 1
560 end
561 coloration_result[element] = color
562 color = min_color
563 end
564 end
565 return self.coloration_result
566 end
567
568 # Check if a related element to the element already use the color
569 private fun is_color_free(element: MType, color: Int): Bool do
570 if conflicts_graph.has_key(element) then
571 for st in conflicts_graph[element] do
572 if coloration_result.has_key(st) and coloration_result[st] == color then return false
573 end
574 end
575 return true
576 end
577
578 # look for unanchored types generated by the same type
579 private fun build_conflicts_graph(elements: Map[MClassType, Set[MType]]) do
580 for mclasstype, mtypes in elements do
581 for mtype in mtypes do
582 for otype in mtypes do
583 if otype == mtype then continue
584 self.add_conflict(mtype, otype)
585 end
586 end
587 end
588 end
589
590 private var conflicts_graph: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
591
592 private fun add_conflict(mtype: MType, otype: MType) do
593 if mtype == otype then return
594 if not self.conflicts_graph.has_key(mtype) then self.conflicts_graph[mtype] = new HashSet[MType]
595 self.conflicts_graph[mtype].add(otype)
596 if not self.conflicts_graph.has_key(otype) then self.conflicts_graph[otype] = new HashSet[MType]
597 self.conflicts_graph[otype].add(mtype)
598 end
599 end
600
601 # Perfect Hashing (PH)
602 # T = type of holder
603 # U = type of elements to hash
604 private class PerfectHasher[T: Object, U: Object]
605
606 var operator: PHOperator
607
608 init do end
609
610 # Compute mask for each holders
611 fun compute_masks(conflicts: Map[T, Set[U]], ids: Map[U, Int]): Map[T, Int] do
612 var masks = new HashMap[T, Int]
613 for mclasstype, mtypes in conflicts do
614 masks[mclasstype] = compute_mask(mtypes, ids)
615 end
616 return masks
617 end
618
619 private fun compute_mask(mtypes: Set[U], ids: Map[U, Int]): Int do
620 var mask = 0
621 loop
622 var used = new List[Int]
623 for mtype in mtypes do
624 var res = operator.op(mask, ids[mtype])
625 if used.has(res) then
626 break
627 else
628 used.add(res)
629 end
630 end
631 if used.length == mtypes.length then break
632 mask += 1
633 end
634 return mask
635 end
636
637 # Compute hash for each element in each holder
638 fun compute_hashes(elements: Map[T, Set[U]], ids: Map[U, Int], masks: Map[T, Int]): Map[T, Map[U, Int]] do
639 var hashes = new HashMap[T, Map[U, Int]]
640 for mclasstype, mtypes in elements do
641 var mask = masks[mclasstype]
642 var inhashes = new HashMap[U, Int]
643 for mtype in mtypes do
644 inhashes[mtype] = operator.op(mask, ids[mtype])
645 end
646 hashes[mclasstype] = inhashes
647 end
648 return hashes
649 end
650 end
651
652 # Abstract operator used for perfect hashing
653 abstract class PHOperator
654 # hash `id` using `mask`
655 fun op(mask: Int, id:Int): Int is abstract
656 end
657
658 # Hashing using modulo (MOD) operator
659 # slower but compact
660 class PHModOperator
661 super PHOperator
662 init do end
663 redef fun op(mask, id) do return mask % id
664 end
665
666 # Hashing using binary and (AND) operator
667 # faster but sparse
668 class PHAndOperator
669 super PHOperator
670 init do end
671 redef fun op(mask, id) do return mask.bin_and(id)
672 end
673
674 # Layout builder for typing tables using perfect hashing (PH)
675 class TypingHasher[E: Object]
676 super PerfectHasher[E, E]
677 super TypingLayoutBuilder[E]
678
679 private var mmodule: MModule
680 private var poset_builder: POSetBuilder[E]
681 private var poset_cache: nullable POSet[E]
682
683 private init(mmodule: MModule, poset_builder: POSetBuilder[E], operator: PHOperator) do
684 self.operator = operator
685 self.mmodule = mmodule
686 self.poset_builder = poset_builder
687 end
688
689 redef fun build_layout(elements: Set[E]): PHLayout[E, E] do
690 poset_cache = poset_builder.build_poset(elements)
691 var result = new PHLayout[E, E]
692 var conflicts = self.build_conflicts(elements)
693 result.ids = self.compute_ids
694 result.masks = self.compute_masks(conflicts, result.ids)
695 result.hashes = self.compute_hashes(conflicts, result.ids, result.masks)
696 return result
697 end
698
699 # Ids start from 1 instead of 0
700 private fun compute_ids: Map[E, Int] do
701 var ids = new HashMap[E, Int]
702 var lin = poset.to_a
703 poset.sort(lin)
704 for e in lin do
705 ids[e] = ids.length + 1
706 end
707 return ids
708 end
709
710 private fun build_conflicts(elements: Set[E]): Map[E, Set[E]] do
711 var conflicts = new HashMap[E, Set[E]]
712 for e in elements do
713 var supers = new HashSet[E]
714 supers.add_all(self.poset[e].greaters)
715 supers.add(e)
716 conflicts[e] = supers
717 end
718 return conflicts
719 end
720 end
721
722 # Layout builder for typing tables with types using perfect hashing (PH)
723 class MTypeHasher
724 super TypingHasher[MType]
725 init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule), operator)
726 end
727
728 # Layout builder for typing tables with classes using perfect hashing (PH)
729 class MClassHasher
730 super TypingHasher[MClass]
731 init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule), operator)
732 end
733
734 # Abstract layout builder for properties tables using perfect hashing (PH)
735 class MPropertyHasher[E: MProperty]
736 super PerfectHasher[MClass, E]
737 super PropertyLayoutBuilder[E]
738
739 type MPROP: MProperty
740
741 var mmodule: MModule
742
743 init(operator: PHOperator, mmodule: MModule) do
744 self.operator = operator
745 self.mmodule = mmodule
746 end
747
748 fun build_poset(mclasses: Set[MClass]): POSet[MClass] do
749 var poset = new POSet[MClass]
750 for e in mclasses do
751 poset.add_node(e)
752 for o in mclasses do
753 if e == o or not mmodule.flatten_mclass_hierarchy.has(e) then continue
754 if e.in_hierarchy(mmodule) < o then poset.add_edge(e, o)
755 end
756 end
757 return poset
758 end
759
760 redef fun build_layout(mclasses) do
761 var result = new PHLayout[MClass, E]
762 var ids = new HashMap[E, Int]
763 var elements = new HashMap[MClass, Set[E]]
764 var poset = build_poset(mclasses)
765 var lin = poset.to_a
766 poset.sort(lin)
767 for mclass in lin.reversed do
768 var mproperties = properties(mclass)
769 for mproperty in mproperties do
770 if ids.has_key(mproperty) then continue
771 ids[mproperty] = ids.length + 1
772 end
773 elements[mclass] = mproperties
774 end
775 result.ids = ids
776 result.pos = ids
777 result.masks = self.compute_masks(elements, ids)
778 result.hashes = self.compute_hashes(elements, ids, result.masks)
779 return result
780 end
781
782 # extract set of properties from mclass
783 private fun properties(mclass: MClass): Set[E] do
784 var properties = new HashSet[E]
785 for mprop in self.mmodule.properties(mclass) do
786 if mprop isa MPROP then properties.add(mprop)
787 end
788 return properties
789 end
790 end
791
792 # Layout builder for vft using perfect hashing (PH)
793 class MMethodHasher
794 super MPropertyHasher[MMethod]
795 redef type MPROP: MMethod
796 init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
797 end
798
799 # Layout builder for attributes tables using perfect hashing (PH)
800 class MAttributeHasher
801 super MPropertyHasher[MAttribute]
802 redef type MPROP: MAttribute
803 init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
804 end
805
806 # Layout builder for virtual types tables using perfect hashing (PH)
807 class MVirtualTypePropHasher
808 super MPropertyHasher[MVirtualTypeProp]
809 redef type MPROP: MVirtualTypeProp
810 init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
811 end
812
813 # Layout builder for resolution tables using perfect hashing (PH)
814 class ResolutionHasher
815 super PerfectHasher[MClassType, MType]
816 super ResolutionLayoutBuilder
817
818 init(operator: PHOperator) do self.operator = operator
819
820 # Compute resolved types masks and hashes
821 redef fun build_layout(elements) do
822 var result = new PHLayout[MClassType, MType]
823 var ids = new HashMap[MType, Int]
824 var color = 1
825 for mclasstype, mclasstypes in elements do
826 for element in mclasstypes do
827 if ids.has_key(element) then continue
828 ids[element] = color
829 color += 1
830 end
831 end
832 result.ids = ids
833 result.pos = ids
834 result.masks = self.compute_masks(elements, ids)
835 result.hashes = self.compute_hashes(elements, ids, result.masks)
836 return result
837 end
838 end