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