From: Jean Privat Date: Mon, 23 Apr 2012 14:06:48 +0000 (-0400) Subject: rta: rename and document runtime_type.nit X-Git-Tag: v0.6~362^2~1 X-Git-Url: http://nitlanguage.org?hp=2a455b006aa47e4dd821eeda4cb4b5a84b3a117a rta: rename and document runtime_type.nit Signed-off-by: Jean Privat --- diff --git a/src/nitstats.nit b/src/nitstats.nit index 5e0c5e5..357d8d1 100644 --- a/src/nitstats.nit +++ b/src/nitstats.nit @@ -25,7 +25,7 @@ module nitstats import modelbuilder import exprbuilder -import runtime_type +import rapid_type_analysis # The job of this visitor is to resolve all types found class ATypeCounterVisitor @@ -515,28 +515,17 @@ end fun runtime_type(modelbuilder: ModelBuilder, mainmodule: MModule) do - var analysis = modelbuilder.do_runtime_type(mainmodule) + var analysis = modelbuilder.do_rapid_type_analysis(mainmodule) print "--- Type Analysis ---" print "Number of live runtime types (instantied resolved type): {analysis.live_types.length}" if analysis.live_types.length < 8 then print "\t{analysis.live_types.join(" ")}" - print "Number of live polymorphic method: {analysis.polymorphic_methods.length}" - if analysis.polymorphic_methods.length < 8 then print "\t{analysis.polymorphic_methods.join(" ")}" print "Number of live method definitions: {analysis.live_methoddefs.length}" if analysis.live_methoddefs.length < 8 then print "\t{analysis.live_methoddefs.join(" ")}" - print "Number of live runtime method definitions (with customization): {analysis.runtime_methods.length}" - if analysis.runtime_methods.length < 8 then print "\t{analysis.runtime_methods.join(" ")}" + print "Number of live customized method definitions: {analysis.live_customized_methoddefs.length}" + if analysis.live_customized_methoddefs.length < 8 then print "\t{analysis.live_customized_methoddefs.join(" ")}" print "Number of live runtime cast types (ie used in as and isa): {analysis.live_cast_types.length}" if analysis.live_cast_types.length < 8 then print "\t{analysis.live_cast_types.join(" ")}" - - for mprop in modelbuilder.model.mproperties do - if not mprop isa MMethod then continue - if analysis.polymorphic_methods.has(mprop) then continue - for methoddef in mprop.mpropdefs do - if analysis.live_methoddefs.has(methoddef) then continue label l - end - #print " {mprop.full_name} is dead" - end label l end # Create a tool context to handle options and paths diff --git a/src/runtime_type.nit b/src/rapid_type_analysis.nit similarity index 72% rename from src/runtime_type.nit rename to src/rapid_type_analysis.nit index 830a86d..3655ffd 100644 --- a/src/runtime_type.nit +++ b/src/rapid_type_analysis.nit @@ -23,21 +23,21 @@ # It is quite efficient but the type set is global and pollutes each call site. # # Heterogenous generics means that each intancied generic class is associated -# to a distinct runtime type. +# to a distinct rapid type. # Heterogenous generics has the advantage to resolve the formal generic # parameters types but increase the number of types. -# More important, heterogenous generics cannot deal with infinite number of runtime +# More important, heterogenous generics cannot deal with infinite number of rapid # types since the analyse tries to list them all (so some programs will be badly refused) # -# Customization means that each method definition is analyzed one per runtime +# Customization means that each method definition is analyzed one per rapid # type of receiver. # Customization have the following advantages: # * `self' is monomorphic # * virtual types are all resolved # * live attributes can be determined on each class -# But has the disadvantage to explode the number of runtime method: each method -# definition for each runtime type that need it -module runtime_type +# But has the disadvantage to explode the number of rapid method: each method +# definition for each rapid type that need it +module rapid_type_analysis import model import modelbuilder @@ -51,10 +51,10 @@ redef class MModule end redef class ModelBuilder - fun do_runtime_type(mainmodule: MModule): RuntimeTypeAnalysis + fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis do var model = self.model - var analysis = new RuntimeTypeAnalysis(self, mainmodule) + var analysis = new RapidTypeAnalysis(self, mainmodule) var nmodule = self.nmodules.first var mainclass = self.try_get_mclass_by_name(nmodule, mainmodule, "Sys") if mainclass == null then return analysis # No entry point @@ -78,20 +78,47 @@ redef class ModelBuilder end end -# RuntimeTypeAnalysis looks for alive runtime types in application. +# RapidTypeAnalysis looks for alive rapid types in application. # The entry point of the analysis is the mainmodule of the application. -class RuntimeTypeAnalysis +class RapidTypeAnalysis + # The modelbuilder used to get the AST. var modelbuilder: ModelBuilder + + # The main module of the analysis. + # Used to perform types operations. var mainmodule: MModule + + # The pool to live types. + # During the analysis, new types are added and combined with + # live_send_sites to determine new customized_methoddefs to visit var live_types: HashSet[MClassType] = new HashSet[MClassType] + + # The pool of types used to perform type checks (isa and as). var live_cast_types: HashSet[MClassType] = new HashSet[MClassType] - var polymorphic_methods: HashSet[MMethod] = new HashSet[MMethod] + + # Live method definitions. + # These method definitions are: + # * visited trough a add_send on an already known live_type + # * visited trough a add_type for an already known live_send_sites + # * visided by a add_monomorphic_send or a add_static_call var live_methoddefs: HashSet[MMethodDef] = new HashSet[MMethodDef] - var runtime_methods: HashSet[RuntimeMethod] = new HashSet[RuntimeMethod] - var live_send_site: HashSet[RuntimeSendSite] = new HashSet[RuntimeSendSite] - private var todo: List[RuntimeMethod] = new List[RuntimeMethod] + # The pool of live customized method definitions + var live_customized_methoddefs: HashSet[CustomizedMethodDef] = new HashSet[CustomizedMethodDef] + # The pool of live RTA send site + # During the analysis, new live_send_sites are added and combined with + # live_types to determine new live_customized_methoddefs to visit + var live_send_sites: HashSet[RTASendSite] = new HashSet[RTASendSite] + + # The customized method definitions that remain to visit + private var todo: List[CustomizedMethodDef] = new List[CustomizedMethodDef] + + # Add a live type to the pool + # + # If the types is already live, then do nothing. + # + # REQUIRE: not mtype.need_anchor fun add_type(mtype: MClassType) do if self.live_types.has(mtype) then return @@ -107,13 +134,12 @@ class RuntimeTypeAnalysis if not npropdef isa AAttrPropdef then continue var nexpr = npropdef.n_expr if nexpr == null then continue - var v = new RuntimeTypeVisitor(self, nclassdef, npropdef.mpropdef.as(not null), mtype) + var v = new RapidTypeVisitor(self, nclassdef, npropdef.mpropdef.as(not null), mtype) v.enter_visit(nexpr) end end - - for rss in self.live_send_site do + for rss in self.live_send_sites do if not mtype.is_subtype(self.mainmodule, null, rss.receiver) then continue if mtype.has_mproperty(self.mainmodule, rss.mmethod) then self.add_monomorphic_send(mtype, rss.mmethod) @@ -121,13 +147,15 @@ class RuntimeTypeAnalysis end end + # Add a send site to the pool + # + # If the send site is already live, then do nothing. fun add_send(mtype: MClassType, mmethod: MMethod) do - var rss = new RuntimeSendSite(mmethod, mtype) - if self.live_send_site.has(rss) then return + var rss = new RTASendSite(mmethod, mtype) + if self.live_send_sites.has(rss) then return - self.live_send_site.add(rss) - self.polymorphic_methods.add(mmethod) + self.live_send_sites.add(rss) for mtype2 in self.live_types do if not mtype2.is_subtype(self.mainmodule, null, mtype) then continue @@ -137,6 +165,10 @@ class RuntimeTypeAnalysis end end + # Add a monomoprhic send. + # The send site is not added to the pool. + # The method just determine the associated method definition then + # performs a static_call fun add_monomorphic_send(mtype: MClassType, mmethod: MMethod) do assert self.live_types.has(mtype) @@ -146,16 +178,19 @@ class RuntimeTypeAnalysis self.add_static_call(mtype, defs.first) end + # Add a customized_methoddefs to the pool + # Is the customized_methoddefs is already live, then do nothing fun add_static_call(mtype: MClassType, mmethoddef: MMethodDef) do assert self.live_types.has(mtype) - var rm = new RuntimeMethod(mmethoddef, mtype) - if self.runtime_methods.has(rm) then return - self.runtime_methods.add(rm) + var rm = new CustomizedMethodDef(mmethoddef, mtype) + if self.live_customized_methoddefs.has(rm) then return + self.live_customized_methoddefs.add(rm) self.todo.add(rm) self.live_methoddefs.add(mmethoddef) end + # Add mtype to the cast pool. fun add_cast_type(mtype: MClassType) do if self.live_cast_types.has(mtype) then return @@ -164,7 +199,7 @@ class RuntimeTypeAnalysis self.live_cast_types.add(mtype) end - # Start the analysis. + # Run the analysis until all visitable method definitions are visited. fun run_analysis do # Force Bool @@ -201,7 +236,7 @@ class RuntimeTypeAnalysis self.add_monomorphic_send(mr.receiver, auto_super_init) end end - var v = new RuntimeTypeVisitor(self, nclassdef, mmethoddef, mr.receiver) + var v = new RapidTypeVisitor(self, nclassdef, mmethoddef, mr.receiver) v.enter_visit(npropdef.n_block) else if npropdef isa ADeferredMethPropdef then # nothing to do (maybe add a waring?) @@ -224,7 +259,8 @@ class RuntimeTypeAnalysis end end -class RuntimeMethod +# A method definitions customized to a specific receiver +class CustomizedMethodDef var mmethoddef: MMethodDef var receiver: MClassType @@ -235,7 +271,7 @@ class RuntimeMethod redef fun ==(o) do - return o isa RuntimeMethod and o.mmethoddef == self.mmethoddef and o.receiver == self.receiver + return o isa CustomizedMethodDef and o.mmethoddef == self.mmethoddef and o.receiver == self.receiver end redef fun hash @@ -244,13 +280,14 @@ class RuntimeMethod end end -class RuntimeSendSite +# A method invokation site bounded by a specific receiver +class RTASendSite var mmethod: MMethod var receiver: MClassType redef fun ==(o) do - return o isa RuntimeSendSite and o.mmethod == self.mmethod and o.receiver == self.receiver + return o isa RTASendSite and o.mmethod == self.mmethod and o.receiver == self.receiver end redef fun hash @@ -259,10 +296,10 @@ class RuntimeSendSite end end -private class RuntimeTypeVisitor +private class RapidTypeVisitor super Visitor - var analysis: RuntimeTypeAnalysis + var analysis: RapidTypeAnalysis var nclassdef: AClassdef @@ -270,7 +307,7 @@ private class RuntimeTypeVisitor var receiver: MClassType - init(analysis: RuntimeTypeAnalysis, nclassdef: AClassdef, mpropdef: MPropDef, receiver: MClassType) + init(analysis: RapidTypeAnalysis, nclassdef: AClassdef, mpropdef: MPropDef, receiver: MClassType) do self.analysis = analysis self.nclassdef = nclassdef @@ -292,44 +329,44 @@ private class RuntimeTypeVisitor fun add_type(mtype: MType) do - var runtimetype = cleanup_type(mtype) - if runtimetype == null then return # we do not care about null + var rapidtype = cleanup_type(mtype) + if rapidtype == null then return # we do not care about null - self.analysis.add_type(runtimetype) - #self.current_node.debug("add_type {runtimetype}") + self.analysis.add_type(rapidtype) + #self.current_node.debug("add_type {rapidtype}") end fun add_send(mtype: MType, mproperty: MMethod) do - var runtimetype = cleanup_type(mtype) - if runtimetype == null then return # we do not care about null + var rapidtype = cleanup_type(mtype) + if rapidtype == null then return # we do not care about null - analysis.add_send(runtimetype, mproperty) + analysis.add_send(rapidtype, mproperty) #self.current_node.debug("add_send {mproperty}") end fun add_monomorphic_send(mtype: MType, mproperty: MMethod) do - var runtimetype = cleanup_type(mtype) - if runtimetype == null then return # we do not care about null + var rapidtype = cleanup_type(mtype) + if rapidtype == null then return # we do not care about null - self.analysis.add_monomorphic_send(runtimetype, mproperty) - #self.current_node.debug("add_static call {runtimetype} {mproperty}") + self.analysis.add_monomorphic_send(rapidtype, mproperty) + #self.current_node.debug("add_monomorphic_send {rapidtype} {mproperty}") end fun add_cast_type(mtype: MType) do - var runtimetype = cleanup_type(mtype) - if runtimetype == null then return # we do not care about null + var rapidtype = cleanup_type(mtype) + if rapidtype == null then return # we do not care about null - self.analysis.add_cast_type(runtimetype) - #self.current_node.debug("add_cast_type {runtimetype}") + self.analysis.add_cast_type(rapidtype) + #self.current_node.debug("add_cast_type {rapidtype}") end redef fun visit(node) do if node == null then return - node.accept_runtime_type_vistor(self) + node.accept_rapid_type_vistor(self) node.visit_all(self) end @@ -354,19 +391,19 @@ private class RuntimeTypeVisitor # Force to get the primitive property named `name' in the instance `recv' or abort fun get_method(recv: MType, name: String): MMethod do - var runtimetype = cleanup_type(recv) - if runtimetype == null then abort + var rapidtype = cleanup_type(recv) + if rapidtype == null then abort var props = self.analysis.mainmodule.model.get_mproperties_by_name(name) if props == null then - self.current_node.debug("Fatal Error: no primitive property {name} on {runtimetype}") + self.current_node.debug("Fatal Error: no primitive property {name} on {rapidtype}") abort end var res: nullable MMethod = null for mprop in props do assert mprop isa MMethod - if not runtimetype.has_mproperty(self.analysis.mainmodule, mprop) then continue - if mprop.is_init and mprop.intro_mclassdef.mclass != runtimetype.mclass then continue + if not rapidtype.has_mproperty(self.analysis.mainmodule, mprop) then continue + if mprop.is_init and mprop.intro_mclassdef.mclass != rapidtype.mclass then continue if res == null then res = mprop else @@ -375,7 +412,7 @@ private class RuntimeTypeVisitor end end if res == null then - self.current_node.debug("Fatal Error: no primitive property {name} on {runtimetype}") + self.current_node.debug("Fatal Error: no primitive property {name} on {rapidtype}") abort end return res @@ -385,34 +422,34 @@ end ### redef class ANode - private fun accept_runtime_type_vistor(v: RuntimeTypeVisitor) + private fun accept_rapid_type_vistor(v: RapidTypeVisitor) do end end redef class AIntExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_type(self.mtype.as(not null)) end end redef class AFloatExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_type(self.mtype.as(not null)) end end redef class ACharExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_type(self.mtype.as(not null)) end end redef class AArrayExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mtype = self.mtype.as(not null) v.add_type(mtype) @@ -424,7 +461,7 @@ redef class AArrayExpr end redef class AStringFormExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mtype = self.mtype.as(not null) v.add_type(mtype) @@ -436,7 +473,7 @@ redef class AStringFormExpr end redef class ASuperstringExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var arraytype = v.get_class("Array").get_mtype([v.get_class("Object").mclass_type]) v.add_type(arraytype) @@ -447,7 +484,7 @@ redef class ASuperstringExpr end redef class ACrangeExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mtype = self.mtype.as(not null) v.add_type(mtype) @@ -457,7 +494,7 @@ redef class ACrangeExpr end redef class AOrangeExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mtype = self.mtype.as(not null) v.add_type(mtype) @@ -467,28 +504,28 @@ redef class AOrangeExpr end redef class ATrueExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_type(self.mtype.as(not null)) end end redef class AFalseExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_type(self.mtype.as(not null)) end end redef class AIsaExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_cast_type(self.cast_type.as(not null)) end end redef class AAsCastExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_cast_type(self.mtype.as(not null)) end @@ -497,7 +534,7 @@ end # redef class ASendExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mproperty = self.mproperty.as(not null) if n_expr isa ASelfExpr then @@ -510,7 +547,7 @@ redef class ASendExpr end redef class ASendReassignFormExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_send(self.read_type.as(not null), self.reassign_property.mproperty) var mproperty = self.mproperty.as(not null) @@ -527,21 +564,21 @@ redef class ASendReassignFormExpr end redef class AVarReassignExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_send(self.read_type.as(not null), self.reassign_property.mproperty) end end redef class AAttrReassignExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do v.add_send(self.read_type.as(not null), self.reassign_property.mproperty) end end redef class ASuperExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var mproperty = self.mproperty if mproperty != null then @@ -562,7 +599,7 @@ redef class ASuperExpr end redef class AForExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var recvtype = self.n_expr.mtype.as(not null) var colltype = v.get_class("Collection").mclassdefs.first.bound_mtype @@ -576,7 +613,7 @@ redef class AForExpr end redef class ANewExpr - redef fun accept_runtime_type_vistor(v) + redef fun accept_rapid_type_vistor(v) do var recvtype = self.mtype.as(not null) v.add_type(recvtype)