X-Git-Url: http://nitlanguage.org diff --git a/src/rapid_type_analysis.nit b/src/rapid_type_analysis.nit index a40ca22..7cbdaf9 100644 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@ -23,17 +23,15 @@ # It is quite efficient but the type set is global and pollutes each call site. module rapid_type_analysis -import model -import modelbuilder -import typing -import auto_super_init +import semantize -import csv # for live_types_to_csv -import ordered_tree # for live_methods_to_tree +private import csv # for live_types_to_csv +private import ordered_tree # for live_methods_to_tree private import more_collections redef class ModelBuilder + # Performs a rapid-type-analysis on the program associated with `mainmodule`. fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis do var analysis = new RapidTypeAnalysis(self, mainmodule) @@ -88,7 +86,7 @@ class RapidTypeAnalysis 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 + mtype = mtype.as_notnullable assert mtype isa MClassType mtype = mtype.mclass.intro.bound_mtype var mproperty = callsite.mproperty @@ -190,19 +188,28 @@ class RapidTypeAnalysis if initprop != null then add_send(maintype, initprop) end - var mainprop = mainmodule.try_get_primitive_method("main", maintype.mclass) + var mainprop = mainmodule.try_get_primitive_method("run", maintype.mclass) or else + mainmodule.try_get_primitive_method("main", maintype.mclass) if mainprop != null then add_send(maintype, mainprop) end + var finalizable_type = mainmodule.finalizable_type + if finalizable_type != null then + var finalize_meth = mainmodule.try_get_primitive_method("finalize", finalizable_type.mclass) + if finalize_meth != null then add_send(finalizable_type, finalize_meth) + end + # Force primitive types force_alive("Bool") force_alive("Int") force_alive("Float") force_alive("Char") + force_alive("Pointer") while not todo.is_empty do var mmethoddef = todo.shift + var mmeth = mmethoddef.mproperty #print "# visit {mmethoddef}" var v = new RapidTypeVisitor(self, mmethoddef.mclassdef.bound_mtype, mmethoddef) @@ -218,27 +225,28 @@ class RapidTypeAnalysis v.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg.mclass, self.mainmodule)) end - - for i in [0..mmethoddef.msignature.arity[ do - var origtype = mmethoddef.mproperty.intro.msignature.mparameters[i].mtype + # TODO? new_msignature + var sig = mmethoddef.msignature.as(not null) + var osig = mmeth.intro.msignature.as(not null) + for i in [0..sig.arity[ do + var origtype = osig.mparameters[i].mtype if not origtype.need_anchor then continue # skip non covariant stuff - var paramtype = mmethoddef.msignature.mparameters[i].mtype - #paramtype = v.cleanup_type(paramtype).as(not null) + var paramtype = sig.mparameters[i].mtype add_cast(paramtype) end if not modelbuilder.mpropdef2npropdef.has_key(mmethoddef) then # It is an init for a class? - if mmethoddef.mproperty.name == "init" then + if mmeth.name == "init" then var nclassdef = self.modelbuilder.mclassdef2nclassdef[mmethoddef.mclassdef] - var super_inits = nclassdef.super_inits - if super_inits != null then - #assert args.length == 1 - for su in super_inits do - v.add_monomorphic_send(v.receiver, su) - end - end + assert mmethoddef == nclassdef.mfree_init + if mmethoddef.mproperty.is_root_init and not mmethoddef.is_intro then + self.add_super_send(v.receiver, mmethoddef) + end + else if mmethoddef.constant_value != null then + # Make the return type live + v.add_type(mmethoddef.msignature.return_mtype.as(MClassType)) else abort end @@ -247,27 +255,26 @@ class RapidTypeAnalysis var npropdef = modelbuilder.mpropdef2npropdef[mmethoddef] - if npropdef isa AConcreteMethPropdef then + if npropdef isa AMethPropdef then var auto_super_inits = npropdef.auto_super_inits if auto_super_inits != null then for auto_super_init in auto_super_inits do v.add_callsite(auto_super_init) end end - else if npropdef isa AInternMethPropdef or - (npropdef isa AExternMethPropdef and npropdef.n_extern != null) then + if npropdef.auto_super_call then + self.add_super_send(v.receiver, mmethoddef) + end + end + + if mmeth.is_new then + v.add_type(v.receiver) + else if mmethoddef.is_intern or mmethoddef.is_extern then # UGLY: We force the "instantation" of the concrete return type if any var ret = mmethoddef.msignature.return_mtype if ret != null and ret isa MClassType and ret.mclass.kind != abstract_kind and ret.mclass.kind != interface_kind then v.add_type(ret) end - else if npropdef isa AExternMethPropdef then - var nclassdef = npropdef.parent.as(AClassdef) - v.enter_visit(npropdef) - else if npropdef isa AExternInitPropdef then - v.add_type(v.receiver) - else - end v.enter_visit(npropdef) @@ -418,11 +425,12 @@ class RapidTypeAnalysis fun add_super_send(recv: MType, mpropdef: MMethodDef) do + assert mpropdef.has_supercall if live_super_sends.has(mpropdef) then return #print "new super prop: {mpropdef}" live_super_sends.add(mpropdef) - for t in live_types do - try_super_send(t, mpropdef) + for c in live_classes do + try_super_send(c.intro.bound_mtype, mpropdef) end end end @@ -460,7 +468,7 @@ class RapidTypeVisitor do mtype = mtype.anchor_to(self.analysis.mainmodule, self.receiver) if mtype isa MNullType then return null - if mtype isa MNullableType then mtype = mtype.mtype + mtype = mtype.as_notnullable assert mtype isa MClassType assert not mtype.need_anchor return mtype @@ -491,6 +499,11 @@ class RapidTypeVisitor fun add_cast_type(mtype: MType) do analysis.add_cast(mtype) fun add_callsite(callsite: nullable CallSite) do if callsite != null then + for m in callsite.mpropdef.initializers do + if m isa MMethod then + analysis.add_send(callsite.recv, m) + end + end analysis.add_send(callsite.recv, callsite.mproperty) analysis.live_callsites.add(callsite) end