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