X-Git-Url: http://nitlanguage.org diff --git a/src/rapid_type_analysis.nit b/src/rapid_type_analysis.nit index ff72fac..a40ca22 100644 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@ -31,6 +31,8 @@ import auto_super_init import csv # for live_types_to_csv import ordered_tree # for live_methods_to_tree +private import more_collections + redef class ModelBuilder fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis do @@ -75,6 +77,36 @@ class RapidTypeAnalysis # Live methods. var live_methods = new HashSet[MMethod] + # Live callsites. + var live_callsites = new HashSet[CallSite] + + private var live_targets_cache = new HashMap2[MType, MProperty, Set[MMethodDef]] + + # The live targets of a specific callsite. + fun live_targets(callsite: CallSite): Set[MMethodDef] + do + var mtype = callsite.recv + var anchor = callsite.anchor + if anchor != null then mtype = mtype.anchor_to(callsite.mmodule, anchor) + if mtype isa MNullableType then mtype = mtype.mtype + assert mtype isa MClassType + mtype = mtype.mclass.intro.bound_mtype + var mproperty = callsite.mproperty + var res = live_targets_cache[mtype, mproperty] + if res != null then return res + res = new ArraySet[MMethodDef] + live_targets_cache[mtype, mproperty] = res + + for c in live_classes do + var tc = c.intro.bound_mtype + if not tc.is_subtype(mainmodule, null, mtype) then continue + var d = mproperty.lookup_first_definition(mainmodule, tc) + res.add d + end + + return res + end + # Live call-to-super. var live_super_sends = new HashSet[MMethodDef] @@ -129,9 +161,16 @@ class RapidTypeAnalysis return tree end - # Methods that are are still candidate to the try_send + # Methods that are still candidate to the try_send private var totry_methods = new HashSet[MMethod] + # Methods that are are no more candidate to the try_send + private var totry_methods_to_remove = new Array[MMethod] + + # Methods that are or were candidate to the try_send + # Used to ensure that try_send is only used once + private var try_methods = new HashSet[MMethod] + # The method definitions that remain to visit private var todo = new List[MMethodDef] @@ -294,6 +333,10 @@ class RapidTypeAnalysis for p in totry_methods do try_send(mtype, p) for p in live_super_sends do try_super_send(mtype, p) + # Remove cleared ones + for p in totry_methods_to_remove do totry_methods.remove(p) + totry_methods_to_remove.clear + var bound_mtype = mtype.anchor_to(mainmodule, recv) for cd in bound_mtype.collect_mclassdefs(mainmodule) do @@ -342,14 +385,15 @@ class RapidTypeAnalysis if not live_methoddefs.has(d) then return end #print "full property: {mpropdef.mproperty} for {mpropdef.mproperty.mpropdefs.length} definitions" - totry_methods.remove(mpropdef.mproperty) + totry_methods_to_remove.add(mpropdef.mproperty) end fun add_send(recv: MType, mproperty: MMethod) do - if live_methods.has(mproperty) then return + if try_methods.has(mproperty) then return #print "new prop: {mproperty}" live_methods.add(mproperty) + try_methods.add(mproperty) if mproperty.mpropdefs.length == 1 then # If there is only one definition, just add the definition and do not try again the property var d = mproperty.mpropdefs.first @@ -436,13 +480,20 @@ class RapidTypeVisitor fun add_type(mtype: MClassType) do analysis.add_new(receiver, mtype) - fun add_monomorphic_send(mtype: MType, mproperty: MMethod) do analysis.try_send(mtype.as(MClassType), mproperty) + fun add_monomorphic_send(mtype: MType, mproperty: MMethod) + do + analysis.live_methods.add(mproperty) + analysis.try_send(mtype.as(MClassType), mproperty) + end fun add_send(mtype: MType, mproperty: MMethod) do analysis.add_send(mtype, mproperty) fun add_cast_type(mtype: MType) do analysis.add_cast(mtype) - fun add_callsite(callsite: nullable CallSite) do if callsite != null then analysis.add_send(callsite.recv, callsite.mproperty) + fun add_callsite(callsite: nullable CallSite) do if callsite != null then + analysis.add_send(callsite.recv, callsite.mproperty) + analysis.live_callsites.add(callsite) + end end ### @@ -515,8 +566,7 @@ redef class ACrangeExpr do var mtype = self.mtype.as(MClassType) v.add_type(mtype) - var prop = v.get_method(mtype, "init") - v.add_monomorphic_send(mtype, prop) + v.add_callsite(init_callsite) end end @@ -525,8 +575,7 @@ redef class AOrangeExpr do var mtype = self.mtype.as(MClassType) v.add_type(mtype) - var prop = v.get_method(mtype, "without_last") - v.add_monomorphic_send(mtype, prop) + v.add_callsite(init_callsite) end end @@ -605,22 +654,17 @@ end redef class AForExpr redef fun accept_rapid_type_visitor(v) do - var recvtype = self.n_expr.mtype.as(not null) - var colltype = self.coltype.as(not null) - var itmeth = v.get_method(colltype, "iterator") - v.add_send(recvtype, itmeth) - var iteratortype = itmeth.intro.msignature.return_mtype.as(MClassType).mclass.intro.bound_mtype - var objtype = v.get_class("Object").mclass_type - v.add_send(objtype, v.get_method(iteratortype, "is_ok")) + v.add_callsite(self.method_iterator) + v.add_callsite(self.method_is_ok) if self.variables.length == 1 then - v.add_send(objtype, v.get_method(iteratortype, "item")) + v.add_callsite(self.method_item) else if self.variables.length == 2 then - v.add_send(objtype, v.get_method(iteratortype, "key")) - v.add_send(objtype, v.get_method(iteratortype, "item")) + v.add_callsite(self.method_key) + v.add_callsite(self.method_item) else abort end - v.add_send(objtype, v.get_method(iteratortype, "next")) + v.add_callsite(self.method_next) end end