1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Graph coloring tools
18 import rapid_type_analysis
# for type coloration
20 abstract class AbstractColoring[E
: Object]
22 private var sorter
: AbstractSorter[E
]
23 private var reverse_sorter
: AbstractSorter[E
]
25 private var core
: Set[E
] = new HashSet[E
]
26 private var crown
: Set[E
] = new HashSet[E
]
27 private var border
: Set[E
] = new HashSet[E
]
29 private var coloration_result
: Map[E
, Int] = new HashMap[E
, Int]
30 private var conflicts_graph_cache
: nullable HashMap[E
, Set[E
]]
32 init(sorter
: AbstractSorter[E
], reverse_sorter
: AbstractSorter[E
]) do
34 self.reverse_sorter
= reverse_sorter
37 fun colorize
(elements
: Collection[E
]): Map[E
, Int] do
38 # tag each element as part of group core, crown or border
43 #print "core: {core.join(", ")}"
44 #print "border: {border.join(", ")}"
45 #print "crown: {crown.join(", ")}"
47 # sort by reverse linearization order
48 var core
= new Array[E
].from
(self.core
)
49 reverse_sorter
.sort
(core
)
50 var border
= new Array[E
].from
(self.border
)
51 reverse_sorter
.sort
(border
)
52 var crown
= new Array[E
].from
(self.crown
)
53 reverse_sorter
.sort
(crown
)
56 #for k, v in conflicts_graph do
58 # print "{k}: {v.join(", ")}"
63 colorize_elements
(core
)
64 colorize_elements
(border
)
65 colorize_elements
(crown
)
67 return coloration_result
70 # Colorize a collection of elements
71 private fun colorize_elements
(elements
: Collection[E
]) do
74 for element
in elements
do
76 while not self.is_color_free
(element
, color
) do
79 coloration_result
[element
] = color
84 # Check if a related element to the element already use the color
85 private fun is_color_free
(element
: E
, color
: Int): Bool do
86 if conflicts_graph
.has_key
(element
) then
87 for st
in conflicts_graph
[element
] do
88 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
91 for st
in self.super_elements
(element
) do
92 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
97 # Tag element as core, crown or border
98 private fun tag_element
(element
: E
) do
99 # Check if sub elements are all in single inheritance
100 var all_subelements_si
= true
101 for subelem
in self.sub_elements
(element
) do
102 if self.is_element_mi
(subelem
) then
103 all_subelements_si
= false
108 # Tag as core, crown or border
109 if self.is_element_mi
(element
) then
110 core
.add_all
(self.super_elements
(element
))
112 if all_subelements_si
then
115 else if not all_subelements_si
then
116 core
.add_all
(self.super_elements
(element
))
123 # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
124 private fun conflicts_graph
: Map[E
, Set[E
]] do
125 if self.conflicts_graph_cache
== null then
126 self.conflicts_graph_cache
= new HashMap[E
, HashSet[E
]]
127 for t
in self.core
do
128 for i
in self.linear_extension
(t
) do
129 if t
== i
then continue
131 var lin_i
= self.linear_extension
(i
)
133 for j
in self.linear_extension
(t
) do
134 if i
== j
or j
== t
then continue
135 var lin_j
= self.linear_extension
(j
)
137 var d_ij
= lin_i
- lin_j
138 var d_ji
= lin_j
- lin_i
141 if not conflicts_graph_cache
.has_key
(ed1
) then conflicts_graph_cache
[ed1
] = new HashSet[E
]
142 # add ed1 x ed2 to conflicts graph
143 for ed2
in d_ji
do conflicts_graph_cache
[ed1
].add
(ed2
)
146 if not conflicts_graph_cache
.has_key
(ed1
) then conflicts_graph_cache
[ed1
] = new HashSet[E
]
147 # add ed1 x ed2 to conflicts graph
148 for ed2
in d_ji
do conflicts_graph_cache
[ed1
].add
(ed2
)
154 return conflicts_graph_cache
.as(not null)
157 # cache for linear_extensions
158 private var linear_extensions_cache
: Map[E
, Array[E
]] = new HashMap[E
, Array[E
]]
160 # Return a linear_extension of super_elements of the element
161 private fun linear_extension
(element
: E
): Array[E
] do
162 if not self.linear_extensions_cache
.has_key
(element
) then
163 var lin
= new Array[E
]
165 lin
.add_all
(self.super_elements
(element
))
166 self.sorter
.sort
(lin
)
167 self.linear_extensions_cache
[element
] = lin
169 return self.linear_extensions_cache
[element
]
172 # Return all super elements (directs and indirects) of an element
173 private fun super_elements
(element
: E
): Collection[E
] is abstract
175 # Return all sub elements (directs and indirects) of an element
176 private fun sub_elements
(element
: E
): Collection[E
] is abstract
178 # Is the element in multiple inheritance ?
179 private fun is_element_mi
(element
: E
): Bool is abstract
182 # MClassType coloring
184 super AbstractColoring[MType]
188 private var mmodule
: MModule
189 private var mtypes
: Set[T
]
192 private var super_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
193 private var sub_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
195 init(mainmodule
: MModule, mtypes
: Set[T
]) do
196 super(new TypeSorter(mainmodule
), new ReverseTypeSorter(mainmodule
))
197 self.mmodule
= mainmodule
202 fun build_type_tables
(mtypes
: Set[T
], colors
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
203 var tables
= new HashMap[T
, Array[nullable T
]]
205 for mtype
in mtypes
do
206 var table
= new Array[nullable T
]
207 var supers
= new HashSet[T
]
208 supers
.add_all
(self.super_elements
(mtype
))
211 var color
= colors
[sup
]
212 if table
.length
<= color
then
213 for i
in [table
.length
.. color
[ do
219 tables
[mtype
] = table
224 redef fun super_elements
(element
) do
225 if not self.super_elements_cache
.has_key
(element
) then
226 var supers
= new HashSet[T
]
227 for mtype
in self.mtypes
do
228 if element
== mtype
then continue
229 if element
.is_subtype
(self.mmodule
, null, mtype
) then
233 self.super_elements_cache
[element
] = supers
235 return self.super_elements_cache
[element
]
238 # Return all direct super elements of an element
239 redef fun is_element_mi
(element
) do
240 return self.super_elements
(element
).length
> 1
243 # Return all sub elements (directs and indirects) of an element
244 redef fun sub_elements
(element
) do
245 if not self.sub_elements_cache
.has_key
(element
) then
246 var subs
= new HashSet[T
]
247 for mtype
in self.mtypes
do
248 if element
== mtype
then continue
249 if mtype
.is_subtype
(self.mmodule
, null, element
) then
253 self.sub_elements_cache
[element
] = subs
255 return self.sub_elements_cache
[element
]
259 class NaiveTypeColoring
262 init(mainmodule
: MModule, mtypes
: Set[T
]) do
263 super(mainmodule
, mtypes
)
266 # naive coloring that use incremental coloring
267 redef fun colorize_elements
(elements
) do
269 self.coloration_result
[e
] = self.coloration_result
.length
274 abstract class TypePerfectHashing
277 init(mainmodule
: MModule, mtypes
: Set[T
]) do
278 super(mainmodule
, mtypes
)
281 fun compute_masks
(elements
: Set[T
], ids
: Map[T
, Int]): Map[T
, Int] do
283 # Create super type list
284 var supers
= new HashSet[T
]
285 supers
.add_all
(self.super_elements
(e
))
287 # Compute the hashing 'mask'
288 self.coloration_result
[e
] = compute_mask
(supers
, ids
)
290 return self.coloration_result
294 fun hash_type_tables
(mtypes
: Set[T
], ids
: Map[T
, Int], masks
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
295 var tables
= new HashMap[T
, Array[nullable T
]]
297 for mtype
in mtypes
do
298 var table
= new Array[nullable T
]
299 var supers
= new HashSet[T
]
300 supers
.add_all
(self.super_elements
(mtype
))
304 var color
= phash
(ids
[sup
], masks
[mtype
])
305 if table
.length
<= color
then
306 for i
in [table
.length
.. color
[ do
312 tables
[mtype
] = table
317 private fun compute_mask
(mtypes
: Set[T
], ids
: Map[T
, Int]): Int do
320 var used
= new List[Int]
322 var res
= op
(mask
, ids
[sup
])
323 if used
.has
(res
) then
329 if used
.length
== mtypes
.length
then break
335 private fun op
(mask
: Int, id
:Int): Int is abstract
336 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
339 class TypeModPerfectHashing
340 super TypePerfectHashing
341 init(mainmodule
: MModule, mtypes
: Set[T
]) do
342 super(mainmodule
, mtypes
)
344 redef fun op
(mask
, id
) do return mask
% id
347 class TypeAndPerfectHashing
348 super TypePerfectHashing
349 init(mainmodule
: MModule, mtypes
: Set[T
]) do
350 super(mainmodule
, mtypes
)
352 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
357 super AbstractColoring[MClass]
361 private var mmodule
: MModule
364 private var super_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
365 private var parent_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
366 private var sub_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
368 init(mainmodule
: MModule) do
369 super(new ClassSorter(mainmodule
), new ReverseClassSorter(mainmodule
))
370 self.mmodule
= mainmodule
374 fun build_type_tables
(mclasses
: Array[T
], colors
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
375 var tables
= new HashMap[T
, Array[nullable T
]]
377 for mclasse
in mclasses
do
378 var table
= new Array[nullable T
]
379 var supers
= new HashSet[T
]
380 supers
.add_all
(self.super_elements
(mclasse
))
383 var color
= colors
[sup
]
384 if table
.length
<= color
then
385 for i
in [table
.length
.. color
[ do
391 tables
[mclasse
] = table
396 redef fun super_elements
(element
) do
397 if not self.super_elements_cache
.has_key
(element
) then
398 var supers
= new HashSet[T
]
399 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
400 for sup
in self.mmodule
.flatten_mclass_hierarchy
[element
].greaters
do
401 if element
== sup
then continue
405 self.super_elements_cache
[element
] = supers
407 return self.super_elements_cache
[element
]
410 private fun parent_elements
(element
: T
): Set[T
] do
411 if not self.parent_elements_cache
.has_key
(element
) then
412 var parents
= new HashSet[T
]
413 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
414 for parent
in self.mmodule
.flatten_mclass_hierarchy
[element
].direct_greaters
do
415 if element
== parent
then continue
419 self.parent_elements_cache
[element
] = parents
421 return self.parent_elements_cache
[element
]
424 # Return all sub elements (directs and indirects) of an element
425 redef fun sub_elements
(element
) do
426 if not self.sub_elements_cache
.has_key
(element
) then
427 var subs
= new HashSet[T
]
428 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
429 for sub
in self.mmodule
.flatten_mclass_hierarchy
[element
].smallers
do
433 self.sub_elements_cache
[element
] = subs
435 return self.sub_elements_cache
[element
]
438 # Return all direct super elements of an element
439 redef fun is_element_mi
(element
) do
440 if not self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then return false
441 return self.mmodule
.flatten_mclass_hierarchy
[element
].direct_greaters
.length
> 1
445 # incremental coloring (very naive)
446 class NaiveClassColoring
449 init(mainmodule
: MModule) do
453 # naive coloring that use incremental coloring
454 redef fun colorize_elements
(elements
: Collection[MClass]) do
456 self.coloration_result
[e
] = self.coloration_result
.length
461 abstract class ClassPerfectHashing
464 init(mainmodule
: MModule) do
468 fun compute_masks
(elements
: Set[T
], ids
: Map[T
, Int]): Map[T
, Int] do
470 # Create super type list
471 var supers
= new HashSet[T
]
472 supers
.add_all
(self.super_elements
(e
))
474 # Compute the hashing 'mask'
475 self.coloration_result
[e
] = compute_mask
(supers
, ids
)
477 return self.coloration_result
481 fun hash_type_tables
(mtypes
: Set[T
], ids
: Map[T
, Int], masks
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
482 var tables
= new HashMap[T
, Array[nullable T
]]
484 for mtype
in mtypes
do
485 var table
= new Array[nullable T
]
486 var supers
= new HashSet[T
]
487 supers
.add_all
(self.super_elements
(mtype
))
491 var color
= phash
(ids
[sup
], masks
[mtype
])
492 if table
.length
<= color
then
493 for i
in [table
.length
.. color
[ do
499 tables
[mtype
] = table
504 private fun compute_mask
(mtypes
: Set[T
], ids
: Map[T
, Int]): Int do
507 var used
= new List[Int]
509 var res
= op
(mask
, ids
[sup
])
510 if used
.has
(res
) then
516 if used
.length
== mtypes
.length
then break
522 private fun op
(mask
: Int, id
:Int): Int is abstract
523 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
526 class ClassModPerfectHashing
527 super ClassPerfectHashing
528 init(mainmodule
: MModule) do
531 redef fun op
(mask
, id
) do return mask
% id
534 class ClassAndPerfectHashing
535 super ClassPerfectHashing
536 init(mainmodule
: MModule) do
539 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
543 class PropertyColoring
545 type MPROP: MProperty
546 type MPROPDEF: MPropDef
548 private var class_coloring
: ClassColoring
549 private var coloration_result
: Map[MPROP, Int] = new HashMap[MPROP, Int]
551 init(class_coloring
: ClassColoring) do
552 self.class_coloring
= class_coloring
555 fun colorize
: Map[MPROP, Int] do
556 colorize_core_properties
557 colorize_crown_properties
558 return self.coloration_result
561 fun build_property_tables
: Map[MClass, Array[nullable MPROPDEF]] do
562 var tables
= new HashMap[MClass, Array[nullable MPROPDEF]]
564 for mclass
in self.class_coloring
.coloration_result
.keys
do
565 var table
= new Array[nullable MPROPDEF]
566 # first, fill table from parents by reverse linearization order
567 var parents
= new Array[MClass]
568 parents
.add_all
(self.class_coloring
.super_elements
(mclass
))
569 self.class_coloring
.reverse_sorter
.sort
(parents
)
570 for parent
in parents
do
571 for mproperty
in self.properties
(parent
) do
572 var color
= self.coloration_result
[mproperty
]
573 if table
.length
<= color
then
574 for i
in [table
.length
.. color
[ do
578 for mpropdef
in mproperty
.mpropdefs
do
579 if mpropdef
.mclassdef
.mclass
== parent
then
580 table
[color
] = mpropdef
586 # then override with local properties
587 for mproperty
in self.properties
(mclass
) do
588 var color
= self.coloration_result
[mproperty
]
589 if table
.length
<= color
then
590 for i
in [table
.length
.. color
[ do
594 for mpropdef
in mproperty
.mpropdefs
do
595 if mpropdef
.mclassdef
.mclass
== mclass
then
596 table
[color
] = mpropdef
600 tables
[mclass
] = table
605 # Colorize properties of the core hierarchy
606 private fun colorize_core_properties
do
607 var mclasses
= self.class_coloring
.core
610 for mclass
in mclasses
do
611 var color
= min_color
613 # if the class is root, get the minimal color
614 if self.class_coloring
.parent_elements
(mclass
).length
== 0 then
615 colorize_elements
(self.properties
(mclass
), color
)
617 # check last color used by parents
618 color
= max_color
(color
, self.class_coloring
.parent_elements
(mclass
))
619 # check max color used in conflicts
620 if self.class_coloring
.conflicts_graph
.has_key
(mclass
) then
621 color
= max_color
(color
, self.class_coloring
.conflicts_graph
[mclass
])
625 colorize_elements
(self.properties
(mclass
), color
)
630 # Colorize properties of the crown hierarchy
631 private fun colorize_crown_properties
do
632 for mclass
in self.class_coloring
.crown
do
633 colorize_elements
(self.properties
(mclass
), max_color
(0, self.class_coloring
.parent_elements
(mclass
)))
637 # Colorize a collection of properties given a starting color
638 private fun colorize_elements
(elements
: Collection[MPROP], start_color
: Int) do
639 for element
in elements
do
640 if self.coloration_result
.has_key
(element
) then continue
641 self.coloration_result
[element
] = start_color
646 private fun max_color
(min_color
: Int, mclasses
: Collection[MClass]): Int do
647 var max_color
= min_color
649 for mclass
in mclasses
do
650 for mproperty
in self.properties
(mclass
) do
651 var color
= min_color
652 if self.coloration_result
.has_key
(mproperty
) then
653 color
= self.coloration_result
[mproperty
]
654 if color
>= max_color
then max_color
= color
+ 1
662 private var properties_cache
: Map[MClass, Set[MPROP]] = new HashMap[MClass, Set[MPROP]]
664 # All 'mproperties' associated to all 'mclassdefs' of the class
665 private fun properties
(mclass
: MClass): Set[MPROP] do
666 if not self.properties_cache
.has_key
(mclass
) then
667 var properties
= new HashSet[MPROP]
668 var parents
= self.class_coloring
.super_elements
(mclass
)
669 for parent
in parents
do
670 properties
.add_all
(self.properties
(parent
))
673 for mclassdef
in mclass
.mclassdefs
do
674 for mpropdef
in mclassdef
.mpropdefs
do
675 var mproperty
= mpropdef
.mproperty
676 if mproperty
isa MPROP then
677 properties
.add
(mproperty
)
681 self.properties_cache
[mclass
] = properties
683 return properties_cache
[mclass
]
689 super PropertyColoring
691 redef type MPROP: MMethod
692 redef type MPROPDEF: MMethodDef
693 init(class_coloring
: ClassColoring) do end
696 # MAttribute coloring
697 class AttributeColoring
698 super PropertyColoring
700 redef type MPROP: MAttribute
701 redef type MPROPDEF: MAttributeDef
702 init(class_coloring
: ClassColoring) do end
705 # MVirtualTypeProp coloring
707 super PropertyColoring
709 redef type MPROP: MVirtualTypeProp
710 redef type MPROPDEF: MVirtualTypeDef
711 init(class_coloring
: ClassColoring) do end
714 class NaiveVTColoring
717 init(class_coloring
: ClassColoring) do end
719 redef fun colorize
: Map[MPROP, Int] do
720 var mclasses
= new HashSet[MClass]
721 mclasses
.add_all
(self.class_coloring
.core
)
722 mclasses
.add_all
(self.class_coloring
.crown
)
725 for mclass
in mclasses
do
726 min_color
= max_color
(min_color
, mclasses
)
727 colorize_elements
(self.properties
(mclass
), min_color
)
729 return self.coloration_result
733 abstract class VTPerfectHashing
736 private var masks
: Map[MClass, Int] = new HashMap[MClass, Int]
738 init(class_coloring
: ClassColoring) do end
740 redef fun colorize
: Map[MPROP, Int] do
741 var mclasses
= new HashSet[MClass]
742 mclasses
.add_all
(self.class_coloring
.core
)
743 mclasses
.add_all
(self.class_coloring
.crown
)
744 for mclass
in mclasses
do
745 var vts
= self.properties
(mclass
)
747 if coloration_result
.has_key
(vt
) then continue
748 coloration_result
[vt
] = coloration_result
.length
+ 1
751 return self.coloration_result
754 fun compute_masks
: Map[MClass, Int] do
755 var mclasses
= new HashSet[MClass]
756 mclasses
.add_all
(self.class_coloring
.core
)
757 mclasses
.add_all
(self.class_coloring
.crown
)
758 for mclass
in mclasses
do
759 self.masks
[mclass
] = compute_mask
(self.properties
(mclass
))
764 private fun compute_mask
(vts
: Set[MPROP]): Int do
767 var used
= new List[Int]
769 var res
= op
(mask
, self.coloration_result
[vt
])
770 if used
.has
(res
) then
776 if used
.length
== vts
.length
then break
782 redef fun build_property_tables
do
783 var tables
= new HashMap[MClass, Array[nullable MPROPDEF]]
785 for mclass
in self.class_coloring
.coloration_result
.keys
do
786 var table
= new Array[nullable MPROPDEF]
787 # first, fill table from parents by reverse linearization order
788 var parents
= new Array[MClass]
789 parents
.add_all
(self.class_coloring
.super_elements
(mclass
))
790 self.class_coloring
.reverse_sorter
.sort
(parents
)
791 for parent
in parents
do
792 for mproperty
in self.properties
(parent
) do
793 var color
= phash
(self.coloration_result
[mproperty
], masks
[mclass
])
794 if table
.length
<= color
then
795 for i
in [table
.length
.. color
[ do
799 for mpropdef
in mproperty
.mpropdefs
do
800 if mpropdef
.mclassdef
.mclass
== parent
then
801 table
[color
] = mpropdef
807 # then override with local properties
808 for mproperty
in self.properties
(mclass
) do
809 var color
= phash
(self.coloration_result
[mproperty
], masks
[mclass
])
810 if table
.length
<= color
then
811 for i
in [table
.length
.. color
[ do
815 for mpropdef
in mproperty
.mpropdefs
do
816 if mpropdef
.mclassdef
.mclass
== mclass
then
817 table
[color
] = mpropdef
821 tables
[mclass
] = table
826 private fun op
(mask
: Int, id
:Int): Int is abstract
827 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
831 class VTModPerfectHashing
832 super VTPerfectHashing
833 init(class_coloring
: ClassColoring) do end
834 redef fun op
(mask
, id
) do return mask
% id
837 class VTAndPerfectHashing
838 super VTPerfectHashing
839 init(class_coloring
: ClassColoring) do end
840 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
843 # MParameterType coloring
845 private var class_coloring
: ClassColoring
846 private var coloration_result
: Map[MParameterType, Int] = new HashMap[MParameterType, Int]
848 init(class_coloring
: ClassColoring) do
849 self.class_coloring
= class_coloring
852 fun colorize
: Map[MParameterType, Int] do
853 colorize_core_properties
854 colorize_crown_properties
855 return self.coloration_result
858 # Colorize properties of the core hierarchy
859 private fun colorize_core_properties
do
860 var mclasses
= self.class_coloring
.core
863 for mclass
in mclasses
do
864 var color
= min_color
866 # if the class is root, get the minimal color
867 if self.class_coloring
.parent_elements
(mclass
).length
== 0 then
868 colorize_elements
(self.fts
(mclass
), color
)
870 # check last color used by parents
871 color
= max_color
(color
, self.class_coloring
.parent_elements
(mclass
))
872 # check max color used in conflicts
873 if self.class_coloring
.conflicts_graph
.has_key
(mclass
) then
874 color
= max_color
(color
, self.class_coloring
.conflicts_graph
[mclass
])
877 colorize_elements
(self.fts
(mclass
), color
)
882 # Colorize properties of the crown hierarchy
883 private fun colorize_crown_properties
do
884 for mclass
in self.class_coloring
.crown
do
885 colorize_elements
(self.fts
(mclass
), max_color
(0, self.class_coloring
.parent_elements
(mclass
)))
889 # Colorize a collection of properties given a starting color
890 private fun colorize_elements
(elements
: Collection[MParameterType], start_color
: Int) do
891 for element
in elements
do
892 if self.coloration_result
.has_key
(element
) then continue
893 self.coloration_result
[element
] = start_color
898 private fun max_color
(min_color
: Int, mclasses
: Collection[MClass]): Int do
899 var max_color
= min_color
901 for mclass
in mclasses
do
902 for ft
in self.fts
(mclass
) do
903 var color
= min_color
904 if self.coloration_result
.has_key
(ft
) then
905 color
= self.coloration_result
[ft
]
906 if color
>= max_color
then max_color
= color
+ 1
914 private var fts_cache
: Map[MClass, Set[MParameterType]] = new HashMap[MClass, Set[MParameterType]]
916 private fun fts
(mclass
: MClass): Set[MParameterType] do
917 if not self.fts_cache
.has_key
(mclass
) then
918 var fts
= new HashSet[MParameterType]
919 var mclass_type
= mclass
.mclass_type
920 if mclass_type
isa MGenericType then
921 for ft
in mclass_type
.arguments
do
922 fts
.add
(ft
.as(MParameterType))
925 self.fts_cache
[mclass
] = fts
927 return fts_cache
[mclass
]
930 fun build_ft_tables
: Map[MClass, Array[nullable MParameterType]] do
931 var tables
= new HashMap[MClass, Array[nullable MParameterType]]
933 for mclass
in self.class_coloring
.coloration_result
.keys
do
934 var table
= new Array[nullable MParameterType]
936 # first, fill table from parents
937 for parent
in self.class_coloring
.super_elements
(mclass
) do
938 for ft
in self.fts
(parent
) do
939 var color
= self.coloration_result
[ft
]
940 if table
.length
<= color
then
941 for i
in [table
.length
.. color
[ do
949 # then override with local properties
950 for ft
in self.fts
(mclass
) do
951 var color
= self.coloration_result
[ft
]
952 if table
.length
<= color
then
953 for i
in [table
.length
.. color
[ do
959 tables
[mclass
] = table
965 class NaiveFTColoring
968 init(class_coloring
: ClassColoring) do end
970 redef fun colorize
: Map[MParameterType, Int] do
971 var mclasses
= new HashSet[MClass]
972 mclasses
.add_all
(self.class_coloring
.core
)
973 mclasses
.add_all
(self.class_coloring
.crown
)
976 for mclass
in mclasses
do
977 min_color
= max_color
(min_color
, mclasses
)
978 colorize_elements
(self.fts
(mclass
), min_color
)
980 return self.coloration_result
984 abstract class FTPerfectHashing
987 private var masks
: Map[MClass, Int] = new HashMap[MClass, Int]
989 init(class_coloring
: ClassColoring) do end
991 redef fun colorize
: Map[MParameterType, Int] do
992 var mclasses
= new HashSet[MClass]
993 mclasses
.add_all
(self.class_coloring
.core
)
994 mclasses
.add_all
(self.class_coloring
.crown
)
995 for mclass
in mclasses
do
996 for ft
in self.fts
(mclass
) do
997 if coloration_result
.has_key
(ft
) then continue
998 coloration_result
[ft
] = coloration_result
.length
+ 1
1001 return self.coloration_result
1004 fun compute_masks
: Map[MClass, Int] do
1005 var mclasses
= new HashSet[MClass]
1006 mclasses
.add_all
(self.class_coloring
.core
)
1007 mclasses
.add_all
(self.class_coloring
.crown
)
1008 for mclass
in mclasses
do
1009 var fts
= new HashSet[MParameterType]
1010 for parent
in self.class_coloring
.super_elements
(mclass
) do
1011 fts
.add_all
(self.fts
(parent
))
1013 fts
.add_all
(self.fts
(mclass
))
1014 self.masks
[mclass
] = compute_mask
(fts
)
1019 private fun compute_mask
(fts
: Set[MParameterType]): Int do
1022 var used
= new List[Int]
1024 var res
= op
(mask
, self.coloration_result
[ft
])
1025 if used
.has
(res
) then
1031 if used
.length
== fts
.length
then break
1037 redef fun build_ft_tables
do
1038 var tables
= new HashMap[MClass, Array[nullable MParameterType]]
1040 for mclass
in self.class_coloring
.coloration_result
.keys
do
1041 var table
= new Array[nullable MParameterType]
1043 # first, fill table from parents
1044 for parent
in self.class_coloring
.super_elements
(mclass
) do
1045 for ft
in self.fts
(parent
) do
1046 var color
= phash
(self.coloration_result
[ft
], masks
[mclass
])
1047 if table
.length
<= color
then
1048 for i
in [table
.length
.. color
[ do
1056 # then override with local properties
1057 for ft
in self.fts
(mclass
) do
1058 var color
= phash
(self.coloration_result
[ft
], masks
[mclass
])
1059 if table
.length
<= color
then
1060 for i
in [table
.length
.. color
[ do
1066 tables
[mclass
] = table
1071 private fun op
(mask
: Int, id
:Int): Int is abstract
1072 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
1075 class FTModPerfectHashing
1076 super FTPerfectHashing
1077 init(class_coloring
: ClassColoring) do end
1078 redef fun op
(mask
, id
) do return mask
% id
1081 class FTAndPerfectHashing
1082 super FTPerfectHashing
1083 init(class_coloring
: ClassColoring) do end
1084 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
1087 # Live Entries coloring
1088 class LiveEntryColoring
1090 private var coloration_result
: Map[MType, Int] = new HashMap[MType, Int]
1091 private var conflicts_graph_cache
: nullable HashMap[MType, Set[MType]]
1092 var livetypes_tables_sizes
: nullable Map[MClass, Array[Int]]
1096 fun colorize
(elements
: Collection[MType]): Map[MType, Int] do
1098 build_conflicts_graph
(elements
)
1101 colorize_elements
(elements
)
1103 return coloration_result
1107 fun build_livetype_tables
(mtypes
: Set[MType]): Map[MClass, Array[nullable Object]] do
1108 var livetypes_tables
= new HashMap[MClass, Array[nullable Object]]
1109 self.livetypes_tables_sizes
= new HashMap[MClass, Array[Int]]
1111 for mtype
in mtypes
do
1112 if mtype
isa MGenericType then
1113 var table
: Array[nullable Object]
1114 var sizes
: Array[Int]
1115 if livetypes_tables
.has_key
(mtype
.mclass
) then
1116 table
= livetypes_tables
[mtype
.mclass
]
1118 table
= new Array[nullable Object]
1119 livetypes_tables
[mtype
.mclass
] = table
1121 if livetypes_tables_sizes
.has_key
(mtype
.mclass
) then
1122 sizes
= livetypes_tables_sizes
[mtype
.mclass
]
1124 sizes
= new Array[Int]
1125 livetypes_tables_sizes
[mtype
.mclass
] = sizes
1127 build_livetype_table
(mtype
, 0, table
, sizes
)
1131 return livetypes_tables
1134 # Build live gentype table recursively
1135 private fun build_livetype_table
(mtype
: MGenericType, current_rank
: Int, table
: Array[nullable Object], sizes
: Array[Int]) do
1136 var ft
= mtype
.arguments
[current_rank
]
1137 if not self.coloration_result
.has_key
(ft
) then return
1138 var color
= self.coloration_result
[ft
]
1140 if current_rank
>= sizes
.length
then
1141 sizes
[current_rank
] = color
+ 1
1142 else if color
>= sizes
[current_rank
] then
1143 sizes
[current_rank
] = color
+ 1
1146 if color
> table
.length
then
1147 for i
in [table
.length
.. color
[ do table
[i
] = null
1150 if current_rank
== mtype
.arguments
.length
- 1 then
1151 table
[color
] = mtype
1153 var ft_table
: Array[nullable Object]
1154 if color
< table
.length
and table
[color
] != null then
1155 ft_table
= table
[color
].as(Array[nullable Object])
1157 ft_table
= new Array[nullable Object]
1159 table
[color
] = ft_table
1160 build_livetype_table
(mtype
, current_rank
+ 1, ft_table
, sizes
)
1164 # Colorize a collection of elements
1165 fun colorize_elements
(elements
: Collection[MType]) do
1168 for element
in elements
do
1169 var color
= min_color
1170 while not self.is_color_free
(element
, color
) do
1173 coloration_result
[element
] = color
1178 # Check if a related element to the element already use the color
1179 private fun is_color_free
(element
: MType, color
: Int): Bool do
1180 if conflicts_graph
.has_key
(element
) then
1181 for st
in conflicts_graph
[element
] do
1182 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
1188 # look for types in the same generic signatures
1189 private fun build_conflicts_graph
(elements
: Collection[MType]) do
1190 # regroup types by classes
1191 var genclasses
= new HashMap[MClass, Set[MType]]
1192 for e
in elements
do
1193 if e
isa MGenericType then
1194 if not genclasses
.has_key
(e
.mclass
) then
1195 genclasses
[e
.mclass
] = new HashSet[MType]
1197 genclasses
[e
.mclass
].add
(e
)
1202 self.conflicts_graph_cache
= new HashMap[MType, Set[MType]]
1203 for mclass
, mtypes
in genclasses
do
1205 for rank
in [0..mclass
.arity
[ do
1206 # for each live type
1207 for mtype
in mtypes
do
1208 var mclasstype
: MClassType
1209 if mtype
isa MNullableType then
1210 mclasstype
= mtype
.mtype
.as(MClassType)
1212 mclasstype
= mtype
.as(MClassType)
1214 var ft
= mclasstype
.arguments
[rank
]
1215 for otype
in mtypes
do
1216 if mtype
== otype
then continue
1217 var oclasstype
: MClassType
1218 if otype
isa MNullableType then
1219 oclasstype
= otype
.mtype
.as(MClassType)
1221 oclasstype
= otype
.as(MClassType)
1223 var oft
= oclasstype
.arguments
[rank
]
1224 self.add_conflict
(ft
, oft
)
1231 private fun add_conflict
(mtype
: MType, otype
: MType) do
1232 if mtype
== otype
then return
1233 if not self.conflicts_graph_cache
.has_key
(mtype
) then self.conflicts_graph_cache
[mtype
] = new HashSet[MType]
1234 self.conflicts_graph_cache
[mtype
].add
(otype
)
1235 if not self.conflicts_graph_cache
.has_key
(otype
) then self.conflicts_graph_cache
[otype
] = new HashSet[MType]
1236 self.conflicts_graph_cache
[otype
].add
(mtype
)
1238 private fun conflicts_graph
: Map[MType, Set[MType]] do return conflicts_graph_cache
.as(not null)
1241 class NaiveLiveEntryColoring
1242 super LiveEntryColoring
1246 redef fun colorize_elements
(elements
: Collection[MType]) do
1248 for element
in elements
do
1249 coloration_result
[element
] = color
1255 # live unanchored coloring
1256 class UnanchoredTypeColoring
1258 private var coloration_result
: Map[MType, Int] = new HashMap[MType, Int]
1259 private var conflicts_graph
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
1263 fun colorize
(elements
: Map[MClassType, Set[MType]]): Map[MType, Int] do
1264 build_conflicts_graph
(elements
)
1265 colorize_elements
(elements
)
1266 return coloration_result
1269 fun build_tables
(elements
: Map[MClassType, Set[MType]]): Map[MClassType, Array[nullable MType]] do
1270 var tables
= new HashMap[MClassType, Array[nullable MType]]
1272 for mclasstype
, mtypes
in elements
do
1273 var table
= new Array[nullable MType]
1274 for mtype
in mtypes
do
1275 var color
= self.coloration_result
[mtype
]
1276 if table
.length
<= color
then
1277 for i
in [table
.length
.. color
[ do
1281 table
[color
] = mtype
1283 tables
[mclasstype
] = table
1288 # Colorize a collection of elements
1289 fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
1291 for mclasstype
, mclasstypes
in elements
do
1292 for element
in mclasstypes
do
1293 if self.coloration_result
.has_key
(element
) then continue
1294 var color
= min_color
1295 while not self.is_color_free
(element
, color
) do
1298 coloration_result
[element
] = color
1304 # Check if a related element to the element already use the color
1305 private fun is_color_free
(element
: MType, color
: Int): Bool do
1306 if conflicts_graph
.has_key
(element
) then
1307 for st
in conflicts_graph
[element
] do
1308 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
1314 # look for unanchored types generated by the same type
1315 private fun build_conflicts_graph
(elements
: Map[MClassType, Set[MType]]) do
1316 for mclasstype
, mtypes
in elements
do
1317 for mtype
in mtypes
do
1318 for otype
in mtypes
do
1319 if otype
== mtype
then continue
1320 self.add_conflict
(mtype
, otype
)
1326 private fun add_conflict
(mtype
: MType, otype
: MType) do
1327 if mtype
== otype
then return
1328 if not self.conflicts_graph
.has_key
(mtype
) then self.conflicts_graph
[mtype
] = new HashSet[MType]
1329 self.conflicts_graph
[mtype
].add
(otype
)
1330 if not self.conflicts_graph
.has_key
(otype
) then self.conflicts_graph
[otype
] = new HashSet[MType]
1331 self.conflicts_graph
[otype
].add
(mtype
)
1335 class NaiveUnanchoredTypeColoring
1336 super UnanchoredTypeColoring
1340 redef fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
1342 for mclasstype
, mclasstypes
in elements
do
1343 for element
in mclasstypes
do
1344 coloration_result
[element
] = color
1351 abstract class UnanchoredTypePerfectHashing
1352 super NaiveUnanchoredTypeColoring
1354 private var masks
: Map[MClassType, Int] = new HashMap[MClassType, Int]
1358 redef fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
1360 for mclasstype
, mclasstypes
in elements
do
1361 for element
in mclasstypes
do
1362 coloration_result
[element
] = color
1368 fun compute_masks
(elements
: Map[MClassType, Set[MType]]): Map[MClassType, Int] do
1369 for mclasstype
, mtypes
in elements
do
1370 self.masks
[mclasstype
] = compute_mask
(mtypes
)
1375 private fun compute_mask
(mtypes
: Set[MType]): Int do
1378 var used
= new List[Int]
1379 for mtype
in mtypes
do
1380 var res
= op
(mask
, self.coloration_result
[mtype
])
1381 if used
.has
(res
) then
1387 if used
.length
== mtypes
.length
then break
1393 redef fun build_tables
(elements
: Map[MClassType, Set[MType]]): Map[MClassType, Array[nullable MType]] do
1394 var tables
= new HashMap[MClassType, Array[nullable MType]]
1396 for mclasstype
, mtypes
in elements
do
1397 var table
= new Array[nullable MType]
1398 for mtype
in mtypes
do
1399 var color
= phash
(self.coloration_result
[mtype
], masks
[mclasstype
])
1400 if table
.length
<= color
then
1401 for i
in [table
.length
.. color
[ do
1405 table
[color
] = mtype
1407 tables
[mclasstype
] = table
1412 private fun op
(mask
: Int, id
:Int): Int is abstract
1413 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
1416 class UnanchoredTypeModPerfectHashing
1417 super UnanchoredTypePerfectHashing
1419 redef fun op
(mask
, id
) do return mask
% id
1422 class UnanchoredTypeAndPerfectHashing
1423 super UnanchoredTypePerfectHashing
1425 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
1431 redef class HashSet[E
]
1432 init from
(elements
: Collection[E
]) do
1434 self.add_all
(elements
)
1438 redef class Array[E
]
1439 init from
(elements
: Collection[E
]) do
1441 self.add_all
(elements
)
1444 # Return a new Array with the elements only contened in 'self' and not in 'o'
1445 fun -(o
: Array[E
]): Array[E
] do
1446 var res
= new Array[E
]
1447 for e
in self do if not o
.has
(e
) then res
.add
(e
)
1454 # Return a linearization of a set of mtypes
1455 private fun linearize_mtypes
(mtypes
: Set[MType]): Array[MType] do
1456 var lin
= new Array[MType].from
(mtypes
)
1457 var sorter
= new TypeSorter(self)
1462 # Return a reverse linearization of a set of mtypes
1463 private fun reverse_linearize_mtypes
(mtypes
: Set[MType]): Array[MType] do
1464 var lin
= new Array[MType].from
(mtypes
)
1465 var sorter
= new ReverseTypeSorter(self)
1470 # Return super types of a `mtype` in `self`
1471 private fun super_mtypes
(mtype
: MType, mtypes
: Set[MType]): Set[MType] do
1472 if not self.super_mtypes_cache
.has_key
(mtype
) then
1473 var supers
= new HashSet[MType]
1474 for otype
in mtypes
do
1475 if otype
== mtype
then continue
1476 if mtype
.is_subtype
(self, null, otype
) then
1480 self.super_mtypes_cache
[mtype
] = supers
1482 return self.super_mtypes_cache
[mtype
]
1485 private var super_mtypes_cache
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
1487 # Return all sub mtypes (directs and indirects) of a `mtype` in `self`
1488 private fun sub_mtypes
(mtype
: MType, mtypes
: Set[MType]): Set[MType] do
1489 if not self.sub_mtypes_cache
.has_key
(mtype
) then
1490 var subs
= new HashSet[MType]
1491 for otype
in mtypes
do
1492 if otype
== mtype
then continue
1493 if otype
.is_subtype
(self, null, mtype
) then
1497 self.sub_mtypes_cache
[mtype
] = subs
1499 return self.sub_mtypes_cache
[mtype
]
1502 private var sub_mtypes_cache
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
1504 # Return a linearization of a set of mclasses
1505 private fun linearize_mclasses
(mclasses
: Set[MClass]): Array[MClass] do
1506 var lin
= new Array[MClass].from
(mclasses
)
1507 var sorter
= new ClassSorter(self)
1512 # Return a reverse linearization of a set of mtypes
1513 private fun reverse_linearize_mclasses
(mclasses
: Set[MClass]): Array[MClass] do
1514 var lin
= new Array[MClass].from
(mclasses
)
1515 var sorter
= new ReverseClassSorter(self)
1520 # Return all super mclasses (directs and indirects) of a `mclass` in `self`
1521 private fun super_mclasses
(mclass
: MClass): Set[MClass] do
1522 if not self.super_mclasses_cache
.has_key
(mclass
) then
1523 var supers
= new HashSet[MClass]
1524 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1525 for sup
in self.flatten_mclass_hierarchy
[mclass
].greaters
do
1526 if sup
== mclass
then continue
1530 self.super_mclasses_cache
[mclass
] = supers
1532 return self.super_mclasses_cache
[mclass
]
1535 private var super_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1537 # Return all parents of a `mclass` in `self`
1538 private fun parent_mclasses
(mclass
: MClass): Set[MClass] do
1539 if not self.parent_mclasses_cache
.has_key
(mclass
) then
1540 var parents
= new HashSet[MClass]
1541 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1542 for sup
in self.flatten_mclass_hierarchy
[mclass
].direct_greaters
do
1543 if sup
== mclass
then continue
1547 self.parent_mclasses_cache
[mclass
] = parents
1549 return self.parent_mclasses_cache
[mclass
]
1552 private var parent_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1554 # Return all sub mclasses (directs and indirects) of a `mclass` in `self`
1555 private fun sub_mclasses
(mclass
: MClass): Set[MClass] do
1556 if not self.sub_mclasses_cache
.has_key
(mclass
) then
1557 var subs
= new HashSet[MClass]
1558 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1559 for sub
in self.flatten_mclass_hierarchy
[mclass
].smallers
do
1560 if sub
== mclass
then continue
1564 self.sub_mclasses_cache
[mclass
] = subs
1566 return self.sub_mclasses_cache
[mclass
]
1569 private var sub_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1571 # All 'mproperties' associated to all 'mclassdefs' of `mclass`
1572 private fun properties
(mclass
: MClass): Set[MProperty] do
1573 if not self.properties_cache
.has_key
(mclass
) then
1574 var properties
= new HashSet[MProperty]
1575 var parents
= self.super_mclasses
(mclass
)
1576 for parent
in parents
do
1577 properties
.add_all
(self.properties
(parent
))
1580 for mclassdef
in mclass
.mclassdefs
do
1581 for mpropdef
in mclassdef
.mpropdefs
do
1582 properties
.add
(mpropdef
.mproperty
)
1585 self.properties_cache
[mclass
] = properties
1587 return properties_cache
[mclass
]
1590 private var properties_cache
: Map[MClass, Set[MProperty]] = new HashMap[MClass, Set[MProperty]]
1593 # A sorter for linearize list of types
1595 super AbstractSorter[MType]
1597 private var mmodule
: MModule
1599 init(mmodule
: MModule) do self.mmodule
= mmodule
1601 redef fun compare
(a
, b
) do
1604 else if a
.is_subtype
(self.mmodule
, null, b
) then
1611 # A sorter for reverse linearization
1612 class ReverseTypeSorter
1615 init(mmodule
: MModule) do end
1617 redef fun compare
(a
, b
) do
1620 else if a
.is_subtype
(self.mmodule
, null, b
) then
1627 # A sorter for linearize list of classes
1628 private class ClassSorter
1629 super AbstractSorter[MClass]
1631 var mmodule
: MModule
1633 redef fun compare
(a
, b
) do
1636 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then
1643 # A sorter for reverse linearization
1644 private class ReverseClassSorter
1645 super AbstractSorter[MClass]
1647 var mmodule
: MModule
1649 redef fun compare
(a
, b
) do
1652 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then