X-Git-Url: http://nitlanguage.org?ds=sidebyside diff --git a/src/separate_compiler.nit b/src/separate_compiler.nit index 4b16636..f5dd05d 100644 --- a/src/separate_compiler.nit +++ b/src/separate_compiler.nit @@ -18,7 +18,6 @@ module separate_compiler import abstract_compiler import layout_builders import rapid_type_analysis -import collect_super_sends import compiler_ffi # Add separate compiler specific options @@ -95,6 +94,11 @@ redef class ModelBuilder for t in mtypes do compiler.compile_type_to_c(t) end + # compile remaining types structures (useless but needed for the symbol resolution at link-time) + for t in compiler.undead_types do + if mtypes.has(t) then continue + compiler.compile_type_to_c(t) + end compiler.display_stats @@ -114,7 +118,6 @@ class SeparateCompiler var runtime_type_analysis: nullable RapidTypeAnalysis private var undead_types: Set[MType] = new HashSet[MType] - private var partial_types: Set[MType] = new HashSet[MType] private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]] private var type_layout: nullable Layout[MType] @@ -271,13 +274,27 @@ class SeparateCompiler end end + # Collect all super calls (dead or not) + var all_super_calls = new HashSet[MMethodDef] + for mmodule in self.mainmodule.in_importation.greaters do + for mclassdef in mmodule.mclassdefs do + for mpropdef in mclassdef.mpropdefs do + if not mpropdef isa MMethodDef then continue + if mpropdef.has_supercall then + all_super_calls.add(mpropdef) + end + end + end + end + # lookup super calls and add it to the list of mmethods to build layout with var super_calls if runtime_type_analysis != null then super_calls = runtime_type_analysis.live_super_sends else - super_calls = modelbuilder.collect_super_sends + super_calls = all_super_calls end + for mmethoddef in super_calls do var mclass = mmethoddef.mclassdef.mclass mmethods[mclass].add(mmethoddef) @@ -292,14 +309,9 @@ class SeparateCompiler self.compile_color_consts(method_layout.pos) # attribute null color to dead supercalls - for mmodule in self.mainmodule.in_importation.greaters do - for mclassdef in mmodule.mclassdefs do - for mpropdef in mclassdef.mpropdefs do - if mpropdef.has_supercall then - compile_color_const(new_visitor, mpropdef, -1) - end - end - end + for mpropdef in all_super_calls do + if super_calls.has(mpropdef) then continue + compile_color_const(new_visitor, mpropdef, -1) end # attributes coloration @@ -443,16 +455,10 @@ class SeparateCompiler var mtypes = new HashSet[MType] mtypes.add_all(self.runtime_type_analysis.live_types) mtypes.add_all(self.runtime_type_analysis.live_cast_types) - mtypes.add_all(self.undead_types) for c in self.box_kinds.keys do mtypes.add(c.mclass_type) end - for mtype in mtypes do - retrieve_partial_types(mtype) - end - mtypes.add_all(self.partial_types) - # Typing Layout var layout_builder: TypingLayoutBuilder[MType] if modelbuilder.toolcontext.opt_bm_typing.value then @@ -581,34 +587,6 @@ class SeparateCompiler return tables end - fun retrieve_partial_types(mtype: MType) do - # add formal types arguments to mtypes - if mtype isa MGenericType then - for ft in mtype.arguments do - if ft.need_anchor then - print("Why do we need anchor here ?") - abort - end - self.partial_types.add(ft) - retrieve_partial_types(ft) - end - end - var mclass_type: MClassType - if mtype isa MNullableType then - mclass_type = mtype.mtype.as(MClassType) - else - mclass_type = mtype.as(MClassType) - end - - # add virtual types to mtypes - for vt in self.mainmodule.properties(mclass_type.mclass) do - if vt isa MVirtualTypeProp then - var anchored = vt.mvirtualtype.lookup_bound(self.mainmodule, mclass_type).anchor_to(self.mainmodule, mclass_type) - self.partial_types.add(anchored) - end - end - end - # Separately compile all the method definitions of the module fun compile_module_to_c(mmodule: MModule) do @@ -630,6 +608,10 @@ class SeparateCompiler # Globaly compile the type structure of a live type fun compile_type_to_c(mtype: MType) do + assert not mtype.need_anchor + var layout = self.type_layout + var is_live = mtype isa MClassType and runtime_type_analysis.live_types.has(mtype) + var is_cast_live = runtime_type_analysis.live_cast_types.has(mtype) var c_name = mtype.c_name var v = new SeparateCompilerVisitor(self) v.add_decl("/* runtime type {mtype} */") @@ -639,39 +621,70 @@ class SeparateCompiler # const struct type_X v.add_decl("const struct type type_{c_name} = \{") - v.add_decl("{self.type_layout.ids[mtype]},") + + # type id (for cast target) + if is_cast_live then + v.add_decl("{layout.ids[mtype]},") + else + v.add_decl("-1, /*CAST DEAD*/") + end + + # type name v.add_decl("\"{mtype}\", /* class_name_string */") - var layout = self.type_layout - if layout isa PHLayout[MType, MType] then - v.add_decl("{layout.masks[mtype]},") + + # type color (for cast target) + if is_cast_live then + if layout isa PHLayout[MType, MType] then + v.add_decl("{layout.masks[mtype]},") + else + v.add_decl("{layout.pos[mtype]},") + end else - v.add_decl("{layout.pos[mtype]},") + v.add_decl("-1, /*CAST DEAD*/") end + + # is_nullable bit if mtype isa MNullableType then v.add_decl("1,") else v.add_decl("0,") end - if compile_type_resolution_table(mtype) then - v.require_declaration("resolution_table_{c_name}") - v.add_decl("&resolution_table_{c_name},") + + # resolution table (for receiver) + if is_live then + var mclass_type = mtype + if mclass_type isa MNullableType then mclass_type = mclass_type.mtype + assert mclass_type isa MClassType + if resolution_tables[mclass_type].is_empty then + v.add_decl("NULL, /*NO RESOLUTIONS*/") + else + compile_type_resolution_table(mtype) + v.require_declaration("resolution_table_{c_name}") + v.add_decl("&resolution_table_{c_name},") + end else - v.add_decl("NULL,") + v.add_decl("NULL, /*DEAD*/") end - v.add_decl("{self.type_tables[mtype].length},") - v.add_decl("\{") - for stype in self.type_tables[mtype] do - if stype == null then - v.add_decl("-1, /* empty */") - else - v.add_decl("{self.type_layout.ids[stype]}, /* {stype} */") + + # cast table (for receiver) + if is_live then + v.add_decl("{self.type_tables[mtype].length},") + v.add_decl("\{") + for stype in self.type_tables[mtype] do + if stype == null then + v.add_decl("-1, /* empty */") + else + v.add_decl("{layout.ids[stype]}, /* {stype} */") + end end + v.add_decl("\},") + else + v.add_decl("0, \{\}, /*DEAD TYPE*/") end - v.add_decl("\},") v.add_decl("\};") end - fun compile_type_resolution_table(mtype: MType): Bool do + fun compile_type_resolution_table(mtype: MType) do var mclass_type: MClassType if mtype isa MNullableType then @@ -679,7 +692,6 @@ class SeparateCompiler else mclass_type = mtype.as(MClassType) end - if not self.resolution_tables.has_key(mclass_type) then return false var layout = self.resolution_layout @@ -714,7 +726,6 @@ class SeparateCompiler end v.add_decl("\}") v.add_decl("\};") - return true end # Globally compile the table of the class mclass @@ -833,7 +844,7 @@ class SeparateCompiler v.add("if({t} == NULL) \{") v.add_abort("type null") v.add("\}") - v.add("if({t}->resolution_table == NULL) \{") + v.add("if({t}->table_size == 0) \{") v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", {t}->name);") v.add_abort("type dead") v.add("\}") @@ -1277,11 +1288,37 @@ class SeparateCompilerVisitor end end + # Check that mtype is a live open type + fun hardening_live_open_type(mtype: MType) + do + if not compiler.modelbuilder.toolcontext.opt_hardening.value then return + self.require_declaration(mtype.const_color) + var col = mtype.const_color + self.add("if({col} == -1) \{") + self.add("fprintf(stderr, \"Resolution of a dead open type: %s\\n\", \"{mtype.to_s.escape_to_c}\");") + self.add_abort("open type dead") + self.add("\}") + end + + # Check that mtype it a pointer to a live cast type + fun hardening_cast_type(t: String) + do + if not compiler.modelbuilder.toolcontext.opt_hardening.value then return + add("if({t} == NULL) \{") + add_abort("cast type null") + add("\}") + add("if({t}->id == -1 || {t}->color == -1) \{") + add("fprintf(stderr, \"Try to cast on a dead cast type: %s\\n\", {t}->name);") + add_abort("cast type dead") + add("\}") + end + redef fun init_instance(mtype) do self.require_declaration("NEW_{mtype.mclass.c_name}") var compiler = self.compiler if mtype isa MGenericType and mtype.need_anchor then + hardening_live_open_type(mtype) link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv) @@ -1334,17 +1371,19 @@ class SeparateCompilerVisitor self.add_decl("const struct type* {type_struct};") # Either with resolution_table with a direct resolution - link_unresolved_type(self.frame.mpropdef.mclassdef, ntype) - self.require_declaration(ntype.const_color) + hardening_live_open_type(mtype) + link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) + self.require_declaration(mtype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then - self.add("{type_struct} = {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {ntype.const_color})];") + self.add("{type_struct} = {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})];") else - self.add("{type_struct} = {recv_type_info}->resolution_table->types[{ntype.const_color}];") + self.add("{type_struct} = {recv_type_info}->resolution_table->types[{mtype.const_color}];") end if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then self.compiler.count_type_test_unresolved[tag] += 1 self.add("count_type_test_unresolved_{tag}++;") end + hardening_cast_type(type_struct) self.add("{cltype} = {type_struct}->color;") self.add("{idtype} = {type_struct}->id;") if maybe_null and accept_null == "0" then @@ -1356,6 +1395,7 @@ class SeparateCompilerVisitor else if ntype isa MClassType then compiler.undead_types.add(mtype) self.require_declaration("type_{mtype.c_name}") + hardening_cast_type("(&type_{mtype.c_name})") self.add("{cltype} = type_{mtype.c_name}.color;") self.add("{idtype} = type_{mtype.c_name}.id;") if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then @@ -1558,6 +1598,7 @@ class SeparateCompilerVisitor assert mtype isa MGenericType var compiler = self.compiler if mtype.need_anchor then + hardening_live_open_type(mtype) link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv)