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
: OrderedSet[E
] = new OrderedSet[E
]
26 private var crown
: OrderedSet[E
] = new OrderedSet[E
]
27 private var border
: OrderedSet[E
] = new OrderedSet[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 reverse_sorter
.sort
(core
)
49 reverse_sorter
.sort
(border
)
50 reverse_sorter
.sort
(crown
)
53 #for k, v in conflicts_graph do
55 # print "{k}: {v.join(", ")}"
60 colorize_elements
(core
)
61 colorize_elements
(border
)
62 colorize_elements
(crown
)
64 return coloration_result
67 # Colorize a collection of elements
68 private fun colorize_elements
(elements
: Collection[E
]) do
71 for element
in elements
do
73 while not self.is_color_free
(element
, color
) do
76 coloration_result
[element
] = color
81 # Check if a related element to the element already use the color
82 private fun is_color_free
(element
: E
, color
: Int): Bool do
83 if conflicts_graph
.has_key
(element
) then
84 for st
in conflicts_graph
[element
] do
85 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
88 for st
in self.super_elements
(element
) do
89 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
94 # Tag element as core, crown or border
95 private fun tag_element
(element
: E
) do
96 # Check if sub elements are all in single inheritance
97 var all_subelements_si
= true
98 for subelem
in self.sub_elements
(element
) do
99 if self.is_element_mi
(subelem
) then
100 all_subelements_si
= false
105 # Tag as core, crown or border
106 if self.is_element_mi
(element
) then
107 core
.add_all
(self.super_elements
(element
))
109 if all_subelements_si
then
112 else if not all_subelements_si
then
113 core
.add_all
(self.super_elements
(element
))
120 # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
121 private fun conflicts_graph
: Map[E
, Set[E
]] do
122 if self.conflicts_graph_cache
== null then
123 self.conflicts_graph_cache
= new HashMap[E
, HashSet[E
]]
124 for t
in self.core
do
125 for i
in self.linear_extension
(t
) do
126 if t
== i
then continue
128 var lin_i
= self.linear_extension
(i
)
130 for j
in self.linear_extension
(t
) do
131 if i
== j
or j
== t
then continue
132 var lin_j
= self.linear_extension
(j
)
134 var d_ij
= lin_i
- lin_j
135 var d_ji
= lin_j
- lin_i
138 if not conflicts_graph_cache
.has_key
(ed1
) then conflicts_graph_cache
[ed1
] = new HashSet[E
]
139 # add ed1 x ed2 to conflicts graph
140 for ed2
in d_ji
do conflicts_graph_cache
[ed1
].add
(ed2
)
143 if not conflicts_graph_cache
.has_key
(ed1
) then conflicts_graph_cache
[ed1
] = new HashSet[E
]
144 # add ed1 x ed2 to conflicts graph
145 for ed2
in d_ji
do conflicts_graph_cache
[ed1
].add
(ed2
)
151 return conflicts_graph_cache
.as(not null)
154 # cache for linear_extensions
155 private var linear_extensions_cache
: Map[E
, OrderedSet[E
]] = new HashMap[E
, OrderedSet[E
]]
157 # Return a linear_extension of super_elements of the element
158 private fun linear_extension
(element
: E
): OrderedSet[E
] do
159 if not self.linear_extensions_cache
.has_key
(element
) then
160 var lin
= new OrderedSet[E
]
162 lin
.add_all
(self.super_elements
(element
))
163 self.sorter
.sort
(lin
)
164 self.linear_extensions_cache
[element
] = lin
166 return self.linear_extensions_cache
[element
]
169 # Return all super elements (directs and indirects) of an element
170 private fun super_elements
(element
: E
): Collection[E
] is abstract
172 # Return all sub elements (directs and indirects) of an element
173 private fun sub_elements
(element
: E
): Collection[E
] is abstract
175 # Is the element in multiple inheritance ?
176 private fun is_element_mi
(element
: E
): Bool is abstract
179 # MClassType coloring
181 super AbstractColoring[MType]
185 private var mmodule
: MModule
186 private var mtypes
: Set[T
]
189 private var super_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
190 private var sub_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
192 init(mainmodule
: MModule, mtypes
: Set[T
]) do
193 super(new TypeSorter(mainmodule
), new ReverseTypeSorter(mainmodule
))
194 self.mmodule
= mainmodule
199 fun build_type_tables
(mtypes
: Set[T
], colors
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
200 var tables
= new HashMap[T
, Array[nullable T
]]
202 for mtype
in mtypes
do
203 var table
= new Array[nullable T
]
204 var supers
= new HashSet[T
]
205 supers
.add_all
(self.super_elements
(mtype
))
208 var color
= colors
[sup
]
209 if table
.length
<= color
then
210 for i
in [table
.length
.. color
[ do
216 tables
[mtype
] = table
221 redef fun super_elements
(element
) do
222 if not self.super_elements_cache
.has_key
(element
) then
223 var supers
= new HashSet[T
]
224 for mtype
in self.mtypes
do
225 if element
== mtype
then continue
226 if element
.is_subtype
(self.mmodule
, null, mtype
) then
230 self.super_elements_cache
[element
] = supers
232 return self.super_elements_cache
[element
]
235 # Return all direct super elements of an element
236 redef fun is_element_mi
(element
) do
237 return self.super_elements
(element
).length
> 1
240 # Return all sub elements (directs and indirects) of an element
241 redef fun sub_elements
(element
) do
242 if not self.sub_elements_cache
.has_key
(element
) then
243 var subs
= new HashSet[T
]
244 for mtype
in self.mtypes
do
245 if element
== mtype
then continue
246 if mtype
.is_subtype
(self.mmodule
, null, element
) then
250 self.sub_elements_cache
[element
] = subs
252 return self.sub_elements_cache
[element
]
256 class NaiveTypeColoring
259 init(mainmodule
: MModule, mtypes
: Set[T
]) do
260 super(mainmodule
, mtypes
)
263 # naive coloring that use incremental coloring
264 redef fun colorize_elements
(elements
) do
266 self.coloration_result
[e
] = self.coloration_result
.length
271 abstract class TypePerfectHashing
274 init(mainmodule
: MModule, mtypes
: Set[T
]) do
275 super(mainmodule
, mtypes
)
278 fun compute_masks
(elements
: Set[T
], ids
: Map[T
, Int]): Map[T
, Int] do
280 # Create super type list
281 var supers
= new HashSet[T
]
282 supers
.add_all
(self.super_elements
(e
))
284 # Compute the hashing 'mask'
285 self.coloration_result
[e
] = compute_mask
(supers
, ids
)
287 return self.coloration_result
291 fun hash_type_tables
(mtypes
: Set[T
], ids
: Map[T
, Int], masks
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
292 var tables
= new HashMap[T
, Array[nullable T
]]
294 for mtype
in mtypes
do
295 var table
= new Array[nullable T
]
296 var supers
= new HashSet[T
]
297 supers
.add_all
(self.super_elements
(mtype
))
301 var color
= phash
(ids
[sup
], masks
[mtype
])
302 if table
.length
<= color
then
303 for i
in [table
.length
.. color
[ do
309 tables
[mtype
] = table
314 private fun compute_mask
(mtypes
: Set[T
], ids
: Map[T
, Int]): Int do
317 var used
= new List[Int]
319 var res
= op
(mask
, ids
[sup
])
320 if used
.has
(res
) then
326 if used
.length
== mtypes
.length
then break
332 private fun op
(mask
: Int, id
:Int): Int is abstract
333 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
336 class TypeModPerfectHashing
337 super TypePerfectHashing
338 init(mainmodule
: MModule, mtypes
: Set[T
]) do
339 super(mainmodule
, mtypes
)
341 redef fun op
(mask
, id
) do return mask
% id
344 class TypeAndPerfectHashing
345 super TypePerfectHashing
346 init(mainmodule
: MModule, mtypes
: Set[T
]) do
347 super(mainmodule
, mtypes
)
349 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
352 # A sorter for linearize list of types
354 super AbstractSorter[MType]
356 private var mmodule
: MModule
358 init(mmodule
: MModule) do self.mmodule
= mmodule
360 redef fun compare
(a
, b
) do
363 else if a
.is_subtype
(self.mmodule
, null, b
) then
370 # A sorter for reverse linearization
371 class ReverseTypeSorter
374 init(mmodule
: MModule) do end
376 redef fun compare
(a
, b
) do
379 else if a
.is_subtype
(self.mmodule
, null, b
) then
388 super AbstractColoring[MClass]
392 private var mmodule
: MModule
395 private var super_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
396 private var parent_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
397 private var sub_elements_cache
: Map[T
, Set[T
]] = new HashMap[T
, Set[T
]]
399 init(mainmodule
: MModule) do
400 super(new ClassSorter(mainmodule
), new ReverseClassSorter(mainmodule
))
401 self.mmodule
= mainmodule
405 fun build_type_tables
(mclasses
: Array[T
], colors
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
406 var tables
= new HashMap[T
, Array[nullable T
]]
408 for mclasse
in mclasses
do
409 var table
= new Array[nullable T
]
410 var supers
= new HashSet[T
]
411 supers
.add_all
(self.super_elements
(mclasse
))
414 var color
= colors
[sup
]
415 if table
.length
<= color
then
416 for i
in [table
.length
.. color
[ do
422 tables
[mclasse
] = table
427 redef fun super_elements
(element
) do
428 if not self.super_elements_cache
.has_key
(element
) then
429 var supers
= new HashSet[T
]
430 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
431 for sup
in self.mmodule
.flatten_mclass_hierarchy
[element
].greaters
do
432 if element
== sup
then continue
436 self.super_elements_cache
[element
] = supers
438 return self.super_elements_cache
[element
]
441 private fun parent_elements
(element
: T
): Set[T
] do
442 if not self.parent_elements_cache
.has_key
(element
) then
443 var parents
= new HashSet[T
]
444 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
445 for parent
in self.mmodule
.flatten_mclass_hierarchy
[element
].direct_greaters
do
446 if element
== parent
then continue
450 self.parent_elements_cache
[element
] = parents
452 return self.parent_elements_cache
[element
]
455 # Return all sub elements (directs and indirects) of an element
456 redef fun sub_elements
(element
) do
457 if not self.sub_elements_cache
.has_key
(element
) then
458 var subs
= new HashSet[T
]
459 if self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then
460 for sub
in self.mmodule
.flatten_mclass_hierarchy
[element
].smallers
do
464 self.sub_elements_cache
[element
] = subs
466 return self.sub_elements_cache
[element
]
469 # Return all direct super elements of an element
470 redef fun is_element_mi
(element
) do
471 if not self.mmodule
.flatten_mclass_hierarchy
.has
(element
) then return false
472 return self.mmodule
.flatten_mclass_hierarchy
[element
].direct_greaters
.length
> 1
476 # incremental coloring (very naive)
477 class NaiveClassColoring
480 init(mainmodule
: MModule) do
484 # naive coloring that use incremental coloring
485 redef fun colorize_elements
(elements
: Collection[MClass]) do
487 self.coloration_result
[e
] = self.coloration_result
.length
492 abstract class ClassPerfectHashing
495 init(mainmodule
: MModule) do
499 fun compute_masks
(elements
: Set[T
], ids
: Map[T
, Int]): Map[T
, Int] do
501 # Create super type list
502 var supers
= new HashSet[T
]
503 supers
.add_all
(self.super_elements
(e
))
505 # Compute the hashing 'mask'
506 self.coloration_result
[e
] = compute_mask
(supers
, ids
)
508 return self.coloration_result
512 fun hash_type_tables
(mtypes
: Set[T
], ids
: Map[T
, Int], masks
: Map[T
, Int]): Map[T
, Array[nullable T
]] do
513 var tables
= new HashMap[T
, Array[nullable T
]]
515 for mtype
in mtypes
do
516 var table
= new Array[nullable T
]
517 var supers
= new HashSet[T
]
518 supers
.add_all
(self.super_elements
(mtype
))
522 var color
= phash
(ids
[sup
], masks
[mtype
])
523 if table
.length
<= color
then
524 for i
in [table
.length
.. color
[ do
530 tables
[mtype
] = table
535 private fun compute_mask
(mtypes
: Set[T
], ids
: Map[T
, Int]): Int do
538 var used
= new List[Int]
540 var res
= op
(mask
, ids
[sup
])
541 if used
.has
(res
) then
547 if used
.length
== mtypes
.length
then break
553 private fun op
(mask
: Int, id
:Int): Int is abstract
554 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
557 class ClassModPerfectHashing
558 super ClassPerfectHashing
559 init(mainmodule
: MModule) do
562 redef fun op
(mask
, id
) do return mask
% id
565 class ClassAndPerfectHashing
566 super ClassPerfectHashing
567 init(mainmodule
: MModule) do
570 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
573 # A sorter for linearize list of classes
574 private class ClassSorter
575 super AbstractSorter[MClass]
579 redef fun compare
(a
, b
) do
582 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then
589 # A sorter for reverse linearization
590 private class ReverseClassSorter
591 super AbstractSorter[MClass]
595 redef fun compare
(a
, b
) do
598 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then
606 class PropertyColoring
608 type MPROP: MProperty
609 type MPROPDEF: MPropDef
611 private var class_coloring
: ClassColoring
612 private var coloration_result
: Map[MPROP, Int] = new HashMap[MPROP, Int]
614 init(class_coloring
: ClassColoring) do
615 self.class_coloring
= class_coloring
618 fun colorize
: Map[MPROP, Int] do
619 colorize_core_properties
620 colorize_crown_properties
621 return self.coloration_result
624 fun build_property_tables
: Map[MClass, Array[nullable MPROPDEF]] do
625 var tables
= new HashMap[MClass, Array[nullable MPROPDEF]]
627 for mclass
in self.class_coloring
.coloration_result
.keys
do
628 var table
= new Array[nullable MPROPDEF]
629 # first, fill table from parents by reverse linearization order
630 var parents
= new OrderedSet[MClass]
631 parents
.add_all
(self.class_coloring
.super_elements
(mclass
))
632 self.class_coloring
.reverse_sorter
.sort
(parents
)
633 for parent
in parents
do
634 for mproperty
in self.properties
(parent
) do
635 var color
= self.coloration_result
[mproperty
]
636 if table
.length
<= color
then
637 for i
in [table
.length
.. color
[ do
641 for mpropdef
in mproperty
.mpropdefs
do
642 if mpropdef
.mclassdef
.mclass
== parent
then
643 table
[color
] = mpropdef
649 # then override with local properties
650 for mproperty
in self.properties
(mclass
) do
651 var color
= self.coloration_result
[mproperty
]
652 if table
.length
<= color
then
653 for i
in [table
.length
.. color
[ do
657 for mpropdef
in mproperty
.mpropdefs
do
658 if mpropdef
.mclassdef
.mclass
== mclass
then
659 table
[color
] = mpropdef
663 tables
[mclass
] = table
668 # Colorize properties of the core hierarchy
669 private fun colorize_core_properties
do
670 var mclasses
= self.class_coloring
.core
673 for mclass
in mclasses
do
674 var color
= min_color
676 # if the class is root, get the minimal color
677 if self.class_coloring
.parent_elements
(mclass
).length
== 0 then
678 colorize_elements
(self.properties
(mclass
), color
)
680 # check last color used by parents
681 color
= max_color
(color
, self.class_coloring
.parent_elements
(mclass
))
682 # check max color used in conflicts
683 if self.class_coloring
.conflicts_graph
.has_key
(mclass
) then
684 color
= max_color
(color
, self.class_coloring
.conflicts_graph
[mclass
])
688 colorize_elements
(self.properties
(mclass
), color
)
693 # Colorize properties of the crown hierarchy
694 private fun colorize_crown_properties
do
695 for mclass
in self.class_coloring
.crown
do
696 colorize_elements
(self.properties
(mclass
), max_color
(0, self.class_coloring
.parent_elements
(mclass
)))
700 # Colorize a collection of properties given a starting color
701 private fun colorize_elements
(elements
: Collection[MPROP], start_color
: Int) do
702 for element
in elements
do
703 if self.coloration_result
.has_key
(element
) then continue
704 self.coloration_result
[element
] = start_color
709 private fun max_color
(min_color
: Int, mclasses
: Collection[MClass]): Int do
710 var max_color
= min_color
712 for mclass
in mclasses
do
713 for mproperty
in self.properties
(mclass
) do
714 var color
= min_color
715 if self.coloration_result
.has_key
(mproperty
) then
716 color
= self.coloration_result
[mproperty
]
717 if color
>= max_color
then max_color
= color
+ 1
725 private var properties_cache
: Map[MClass, Set[MPROP]] = new HashMap[MClass, Set[MPROP]]
727 # All 'mproperties' associated to all 'mclassdefs' of the class
728 private fun properties
(mclass
: MClass): Set[MPROP] do
729 if not self.properties_cache
.has_key
(mclass
) then
730 var properties
= new HashSet[MPROP]
731 var parents
= self.class_coloring
.super_elements
(mclass
)
732 for parent
in parents
do
733 properties
.add_all
(self.properties
(parent
))
736 for mclassdef
in mclass
.mclassdefs
do
737 for mpropdef
in mclassdef
.mpropdefs
do
738 var mproperty
= mpropdef
.mproperty
739 if mproperty
isa MPROP then
740 properties
.add
(mproperty
)
744 self.properties_cache
[mclass
] = properties
746 return properties_cache
[mclass
]
752 super PropertyColoring
754 redef type MPROP: MMethod
755 redef type MPROPDEF: MMethodDef
756 init(class_coloring
: ClassColoring) do end
759 # MAttribute coloring
760 class AttributeColoring
761 super PropertyColoring
763 redef type MPROP: MAttribute
764 redef type MPROPDEF: MAttributeDef
765 init(class_coloring
: ClassColoring) do end
768 # MVirtualTypeProp coloring
770 super PropertyColoring
772 redef type MPROP: MVirtualTypeProp
773 redef type MPROPDEF: MVirtualTypeDef
774 init(class_coloring
: ClassColoring) do end
777 class NaiveVTColoring
780 init(class_coloring
: ClassColoring) do end
782 redef fun colorize
: Map[MPROP, Int] do
783 var mclasses
= new HashSet[MClass]
784 mclasses
.add_all
(self.class_coloring
.core
)
785 mclasses
.add_all
(self.class_coloring
.crown
)
788 for mclass
in mclasses
do
789 min_color
= max_color
(min_color
, mclasses
)
790 colorize_elements
(self.properties
(mclass
), min_color
)
792 return self.coloration_result
796 abstract class VTPerfectHashing
799 private var masks
: Map[MClass, Int] = new HashMap[MClass, Int]
801 init(class_coloring
: ClassColoring) do end
803 redef fun colorize
: Map[MPROP, Int] do
804 var mclasses
= new HashSet[MClass]
805 mclasses
.add_all
(self.class_coloring
.core
)
806 mclasses
.add_all
(self.class_coloring
.crown
)
807 for mclass
in mclasses
do
808 var vts
= self.properties
(mclass
)
810 if coloration_result
.has_key
(vt
) then continue
811 coloration_result
[vt
] = coloration_result
.length
+ 1
814 return self.coloration_result
817 fun compute_masks
: Map[MClass, Int] do
818 var mclasses
= new HashSet[MClass]
819 mclasses
.add_all
(self.class_coloring
.core
)
820 mclasses
.add_all
(self.class_coloring
.crown
)
821 for mclass
in mclasses
do
822 self.masks
[mclass
] = compute_mask
(self.properties
(mclass
))
827 private fun compute_mask
(vts
: Set[MPROP]): Int do
830 var used
= new List[Int]
832 var res
= op
(mask
, self.coloration_result
[vt
])
833 if used
.has
(res
) then
839 if used
.length
== vts
.length
then break
845 redef fun build_property_tables
do
846 var tables
= new HashMap[MClass, Array[nullable MPROPDEF]]
848 for mclass
in self.class_coloring
.coloration_result
.keys
do
849 var table
= new Array[nullable MPROPDEF]
850 # first, fill table from parents by reverse linearization order
851 var parents
= new OrderedSet[MClass]
852 parents
.add_all
(self.class_coloring
.super_elements
(mclass
))
853 self.class_coloring
.reverse_sorter
.sort
(parents
)
854 for parent
in parents
do
855 for mproperty
in self.properties
(parent
) do
856 var color
= phash
(self.coloration_result
[mproperty
], masks
[mclass
])
857 if table
.length
<= color
then
858 for i
in [table
.length
.. color
[ do
862 for mpropdef
in mproperty
.mpropdefs
do
863 if mpropdef
.mclassdef
.mclass
== parent
then
864 table
[color
] = mpropdef
870 # then override with local properties
871 for mproperty
in self.properties
(mclass
) do
872 var color
= phash
(self.coloration_result
[mproperty
], masks
[mclass
])
873 if table
.length
<= color
then
874 for i
in [table
.length
.. color
[ do
878 for mpropdef
in mproperty
.mpropdefs
do
879 if mpropdef
.mclassdef
.mclass
== mclass
then
880 table
[color
] = mpropdef
884 tables
[mclass
] = table
889 private fun op
(mask
: Int, id
:Int): Int is abstract
890 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
894 class VTModPerfectHashing
895 super VTPerfectHashing
896 init(class_coloring
: ClassColoring) do end
897 redef fun op
(mask
, id
) do return mask
% id
900 class VTAndPerfectHashing
901 super VTPerfectHashing
902 init(class_coloring
: ClassColoring) do end
903 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
906 # MParameterType coloring
908 private var class_coloring
: ClassColoring
909 private var coloration_result
: Map[MParameterType, Int] = new HashMap[MParameterType, Int]
911 init(class_coloring
: ClassColoring) do
912 self.class_coloring
= class_coloring
915 fun colorize
: Map[MParameterType, Int] do
916 colorize_core_properties
917 colorize_crown_properties
918 return self.coloration_result
921 # Colorize properties of the core hierarchy
922 private fun colorize_core_properties
do
923 var mclasses
= self.class_coloring
.core
926 for mclass
in mclasses
do
927 var color
= min_color
929 # if the class is root, get the minimal color
930 if self.class_coloring
.parent_elements
(mclass
).length
== 0 then
931 colorize_elements
(self.fts
(mclass
), color
)
933 # check last color used by parents
934 color
= max_color
(color
, self.class_coloring
.parent_elements
(mclass
))
935 # check max color used in conflicts
936 if self.class_coloring
.conflicts_graph
.has_key
(mclass
) then
937 color
= max_color
(color
, self.class_coloring
.conflicts_graph
[mclass
])
940 colorize_elements
(self.fts
(mclass
), color
)
945 # Colorize properties of the crown hierarchy
946 private fun colorize_crown_properties
do
947 for mclass
in self.class_coloring
.crown
do
948 colorize_elements
(self.fts
(mclass
), max_color
(0, self.class_coloring
.parent_elements
(mclass
)))
952 # Colorize a collection of properties given a starting color
953 private fun colorize_elements
(elements
: Collection[MParameterType], start_color
: Int) do
954 for element
in elements
do
955 if self.coloration_result
.has_key
(element
) then continue
956 self.coloration_result
[element
] = start_color
961 private fun max_color
(min_color
: Int, mclasses
: Collection[MClass]): Int do
962 var max_color
= min_color
964 for mclass
in mclasses
do
965 for ft
in self.fts
(mclass
) do
966 var color
= min_color
967 if self.coloration_result
.has_key
(ft
) then
968 color
= self.coloration_result
[ft
]
969 if color
>= max_color
then max_color
= color
+ 1
977 private var fts_cache
: Map[MClass, Set[MParameterType]] = new HashMap[MClass, Set[MParameterType]]
979 private fun fts
(mclass
: MClass): Set[MParameterType] do
980 if not self.fts_cache
.has_key
(mclass
) then
981 var fts
= new HashSet[MParameterType]
982 var mclass_type
= mclass
.mclass_type
983 if mclass_type
isa MGenericType then
984 for ft
in mclass_type
.arguments
do
985 fts
.add
(ft
.as(MParameterType))
988 self.fts_cache
[mclass
] = fts
990 return fts_cache
[mclass
]
993 fun build_ft_tables
: Map[MClass, Array[nullable MParameterType]] do
994 var tables
= new HashMap[MClass, Array[nullable MParameterType]]
996 for mclass
in self.class_coloring
.coloration_result
.keys
do
997 var table
= new Array[nullable MParameterType]
999 # first, fill table from parents
1000 for parent
in self.class_coloring
.super_elements
(mclass
) do
1001 for ft
in self.fts
(parent
) do
1002 var color
= self.coloration_result
[ft
]
1003 if table
.length
<= color
then
1004 for i
in [table
.length
.. color
[ do
1012 # then override with local properties
1013 for ft
in self.fts
(mclass
) do
1014 var color
= self.coloration_result
[ft
]
1015 if table
.length
<= color
then
1016 for i
in [table
.length
.. color
[ do
1022 tables
[mclass
] = table
1028 class NaiveFTColoring
1031 init(class_coloring
: ClassColoring) do end
1033 redef fun colorize
: Map[MParameterType, Int] do
1034 var mclasses
= new HashSet[MClass]
1035 mclasses
.add_all
(self.class_coloring
.core
)
1036 mclasses
.add_all
(self.class_coloring
.crown
)
1039 for mclass
in mclasses
do
1040 min_color
= max_color
(min_color
, mclasses
)
1041 colorize_elements
(self.fts
(mclass
), min_color
)
1043 return self.coloration_result
1047 abstract class FTPerfectHashing
1050 private var masks
: Map[MClass, Int] = new HashMap[MClass, Int]
1052 init(class_coloring
: ClassColoring) do end
1054 redef fun colorize
: Map[MParameterType, Int] do
1055 var mclasses
= new HashSet[MClass]
1056 mclasses
.add_all
(self.class_coloring
.core
)
1057 mclasses
.add_all
(self.class_coloring
.crown
)
1058 for mclass
in mclasses
do
1059 for ft
in self.fts
(mclass
) do
1060 if coloration_result
.has_key
(ft
) then continue
1061 coloration_result
[ft
] = coloration_result
.length
+ 1
1064 return self.coloration_result
1067 fun compute_masks
: Map[MClass, Int] do
1068 var mclasses
= new HashSet[MClass]
1069 mclasses
.add_all
(self.class_coloring
.core
)
1070 mclasses
.add_all
(self.class_coloring
.crown
)
1071 for mclass
in mclasses
do
1072 var fts
= new HashSet[MParameterType]
1073 for parent
in self.class_coloring
.super_elements
(mclass
) do
1074 fts
.add_all
(self.fts
(parent
))
1076 fts
.add_all
(self.fts
(mclass
))
1077 self.masks
[mclass
] = compute_mask
(fts
)
1082 private fun compute_mask
(fts
: Set[MParameterType]): Int do
1085 var used
= new List[Int]
1087 var res
= op
(mask
, self.coloration_result
[ft
])
1088 if used
.has
(res
) then
1094 if used
.length
== fts
.length
then break
1100 redef fun build_ft_tables
do
1101 var tables
= new HashMap[MClass, Array[nullable MParameterType]]
1103 for mclass
in self.class_coloring
.coloration_result
.keys
do
1104 var table
= new Array[nullable MParameterType]
1106 # first, fill table from parents
1107 for parent
in self.class_coloring
.super_elements
(mclass
) do
1108 for ft
in self.fts
(parent
) do
1109 var color
= phash
(self.coloration_result
[ft
], masks
[mclass
])
1110 if table
.length
<= color
then
1111 for i
in [table
.length
.. color
[ do
1119 # then override with local properties
1120 for ft
in self.fts
(mclass
) do
1121 var color
= phash
(self.coloration_result
[ft
], masks
[mclass
])
1122 if table
.length
<= color
then
1123 for i
in [table
.length
.. color
[ do
1129 tables
[mclass
] = table
1134 private fun op
(mask
: Int, id
:Int): Int is abstract
1135 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
1138 class FTModPerfectHashing
1139 super FTPerfectHashing
1140 init(class_coloring
: ClassColoring) do end
1141 redef fun op
(mask
, id
) do return mask
% id
1144 class FTAndPerfectHashing
1145 super FTPerfectHashing
1146 init(class_coloring
: ClassColoring) do end
1147 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
1150 # Live Entries coloring
1151 class LiveEntryColoring
1153 private var coloration_result
: Map[MType, Int] = new HashMap[MType, Int]
1154 private var conflicts_graph_cache
: nullable HashMap[MType, Set[MType]]
1155 var livetypes_tables_sizes
: nullable Map[MClass, Array[Int]]
1159 fun colorize
(elements
: Collection[MType]): Map[MType, Int] do
1161 build_conflicts_graph
(elements
)
1164 colorize_elements
(elements
)
1166 return coloration_result
1170 fun build_livetype_tables
(mtypes
: Set[MType]): Map[MClass, Array[nullable Object]] do
1171 var livetypes_tables
= new HashMap[MClass, Array[nullable Object]]
1172 self.livetypes_tables_sizes
= new HashMap[MClass, Array[Int]]
1174 for mtype
in mtypes
do
1175 if mtype
isa MGenericType then
1176 var table
: Array[nullable Object]
1177 var sizes
: Array[Int]
1178 if livetypes_tables
.has_key
(mtype
.mclass
) then
1179 table
= livetypes_tables
[mtype
.mclass
]
1181 table
= new Array[nullable Object]
1182 livetypes_tables
[mtype
.mclass
] = table
1184 if livetypes_tables_sizes
.has_key
(mtype
.mclass
) then
1185 sizes
= livetypes_tables_sizes
[mtype
.mclass
]
1187 sizes
= new Array[Int]
1188 livetypes_tables_sizes
[mtype
.mclass
] = sizes
1190 build_livetype_table
(mtype
, 0, table
, sizes
)
1194 return livetypes_tables
1197 # Build live gentype table recursively
1198 private fun build_livetype_table
(mtype
: MGenericType, current_rank
: Int, table
: Array[nullable Object], sizes
: Array[Int]) do
1199 var ft
= mtype
.arguments
[current_rank
]
1200 if not self.coloration_result
.has_key
(ft
) then return
1201 var color
= self.coloration_result
[ft
]
1203 if current_rank
>= sizes
.length
then
1204 sizes
[current_rank
] = color
+ 1
1205 else if color
>= sizes
[current_rank
] then
1206 sizes
[current_rank
] = color
+ 1
1209 if color
> table
.length
then
1210 for i
in [table
.length
.. color
[ do table
[i
] = null
1213 if current_rank
== mtype
.arguments
.length
- 1 then
1214 table
[color
] = mtype
1216 var ft_table
: Array[nullable Object]
1217 if color
< table
.length
and table
[color
] != null then
1218 ft_table
= table
[color
].as(Array[nullable Object])
1220 ft_table
= new Array[nullable Object]
1222 table
[color
] = ft_table
1223 build_livetype_table
(mtype
, current_rank
+ 1, ft_table
, sizes
)
1227 # Colorize a collection of elements
1228 fun colorize_elements
(elements
: Collection[MType]) do
1231 for element
in elements
do
1232 var color
= min_color
1233 while not self.is_color_free
(element
, color
) do
1236 coloration_result
[element
] = color
1241 # Check if a related element to the element already use the color
1242 private fun is_color_free
(element
: MType, color
: Int): Bool do
1243 if conflicts_graph
.has_key
(element
) then
1244 for st
in conflicts_graph
[element
] do
1245 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
1251 # look for types in the same generic signatures
1252 private fun build_conflicts_graph
(elements
: Collection[MType]) do
1253 # regroup types by classes
1254 var genclasses
= new HashMap[MClass, Set[MType]]
1255 for e
in elements
do
1256 if e
isa MGenericType then
1257 if not genclasses
.has_key
(e
.mclass
) then
1258 genclasses
[e
.mclass
] = new HashSet[MType]
1260 genclasses
[e
.mclass
].add
(e
)
1265 self.conflicts_graph_cache
= new HashMap[MType, Set[MType]]
1266 for mclass
, mtypes
in genclasses
do
1268 for rank
in [0..mclass
.arity
[ do
1269 # for each live type
1270 for mtype
in mtypes
do
1271 var mclasstype
: MClassType
1272 if mtype
isa MNullableType then
1273 mclasstype
= mtype
.mtype
.as(MClassType)
1275 mclasstype
= mtype
.as(MClassType)
1277 var ft
= mclasstype
.arguments
[rank
]
1278 for otype
in mtypes
do
1279 if mtype
== otype
then continue
1280 var oclasstype
: MClassType
1281 if otype
isa MNullableType then
1282 oclasstype
= otype
.mtype
.as(MClassType)
1284 oclasstype
= otype
.as(MClassType)
1286 var oft
= oclasstype
.arguments
[rank
]
1287 self.add_conflict
(ft
, oft
)
1294 private fun add_conflict
(mtype
: MType, otype
: MType) do
1295 if mtype
== otype
then return
1296 if not self.conflicts_graph_cache
.has_key
(mtype
) then self.conflicts_graph_cache
[mtype
] = new HashSet[MType]
1297 self.conflicts_graph_cache
[mtype
].add
(otype
)
1298 if not self.conflicts_graph_cache
.has_key
(otype
) then self.conflicts_graph_cache
[otype
] = new HashSet[MType]
1299 self.conflicts_graph_cache
[otype
].add
(mtype
)
1301 private fun conflicts_graph
: Map[MType, Set[MType]] do return conflicts_graph_cache
.as(not null)
1304 class NaiveLiveEntryColoring
1305 super LiveEntryColoring
1309 redef fun colorize_elements
(elements
: Collection[MType]) do
1311 for element
in elements
do
1312 coloration_result
[element
] = color
1327 init from
(elements
: Set[E
]) do
1328 self.add_all
(elements
)
1332 if not self.has
(e
) then
1337 # Return a new OrderedSet with the elements only contened in 'self' and not in 'o'
1338 fun -(o
: OrderedSet[E
]): OrderedSet[E
] do
1339 var res
= new OrderedSet[E
]
1340 for e
in self do if not o
.has
(e
) then res
.add
(e
)
1344 # Linearize a set of elements
1345 fun linearize
(sorter
: AbstractSorter[E
]) do