# --semi-global
var opt_semi_global = new OptionBool("Enable all semi-global optimizations", "--semi-global")
# --no-colo-dead-methods
- var opt_no_colo_dead_methods = new OptionBool("Do not colorize dead methods", "--no-colo-dead-methods")
+ var opt_colo_dead_methods = new OptionBool("Force colorization of dead methods", "--colo-dead-methods")
# --tables-metrics
var opt_tables_metrics: OptionBool = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
self.option_context.add_option(self.opt_no_union_attribute)
self.option_context.add_option(self.opt_no_shortcut_equate)
self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global)
- self.option_context.add_option(self.opt_no_colo_dead_methods)
+ self.option_context.add_option(self.opt_colo_dead_methods)
self.option_context.add_option(self.opt_tables_metrics)
end
# The main function of the C
compiler.new_file("{mainmodule.name}.main")
+ compiler.compile_nitni_global_ref_functions
compiler.compile_main_function
+ compiler.compile_finalizer_function
# compile methods
for m in mainmodule.in_importation.greaters do
var rta = runtime_type_analysis
# Layouts
- var mclasses = new HashSet[MClass].from(modelbuilder.model.mclasses)
var poset = mainmodule.flatten_mclass_hierarchy
+ var mclasses = new HashSet[MClass].from(poset)
var colorer = new POSetColorer[MClass]
colorer.colorize(poset)
mattributes[mclass] = new HashSet[MAttribute]
for mprop in self.mainmodule.properties(mclass) do
if mprop isa MMethod then
- if modelbuilder.toolcontext.opt_no_colo_dead_methods.value and rta != null and not rta.live_methods.has(mprop) then
+ if not modelbuilder.toolcontext.opt_colo_dead_methods.value and rta != null and not rta.live_methods.has(mprop) then
dead_methods.add(mprop)
continue
end
var tables = new HashMap[MClass, Array[nullable MPropDef]]
for mclass in mclasses do
var table = new Array[nullable MPropDef]
- var supercalls = new List[MMethodDef]
+ tables[mclass] = table
- # first, fill table from parents by reverse linearization order
- var parents = new Array[MClass]
- if mainmodule.flatten_mclass_hierarchy.has(mclass) then
- parents = mclass.in_hierarchy(mainmodule).greaters.to_a
- self.mainmodule.linearize_mclasses(parents)
- end
+ var mproperties = self.mainmodule.properties(mclass)
+ var mtype = mclass.intro.bound_mtype
- for parent in parents do
- if parent == mclass then continue
- for mproperty in self.mainmodule.properties(parent) do
- if not mproperty isa MMethod then continue
- if not method_colors.has_key(mproperty) then continue
- var color = method_colors[mproperty]
- if table.length <= color then
- for i in [table.length .. color[ do
- table[i] = null
- end
- end
- for mpropdef in mproperty.mpropdefs do
- if mpropdef.mclassdef.mclass == parent then
- table[color] = mpropdef
- end
- end
- end
-
- # lookup for super calls in super classes
- for mmethoddef in super_calls do
- for mclassdef in parent.mclassdefs do
- if mclassdef.mpropdefs.has(mmethoddef) then
- supercalls.add(mmethoddef)
- end
- end
- end
- end
-
- # then override with local properties
- for mproperty in self.mainmodule.properties(mclass) do
+ for mproperty in mproperties do
if not mproperty isa MMethod then continue
if not method_colors.has_key(mproperty) then continue
var color = method_colors[mproperty]
table[i] = null
end
end
- for mpropdef in mproperty.mpropdefs do
- if mpropdef.mclassdef.mclass == mclass then
- table[color] = mpropdef
- end
- end
+ table[color] = mproperty.lookup_first_definition(mainmodule, mtype)
end
- # lookup for super calls in local class
- for mmethoddef in super_calls do
- for mclassdef in mclass.mclassdefs do
- if mclassdef.mpropdefs.has(mmethoddef) then
- supercalls.add(mmethoddef)
- end
- end
- end
- # insert super calls in table according to receiver
- for supercall in supercalls do
+ for supercall in super_calls do
+ if not mtype.collect_mclassdefs(mainmodule).has(supercall.mclassdef) then continue
+
var color = method_colors[supercall]
if table.length <= color then
for i in [table.length .. color[ do
table[i] = null
end
end
- var mmethoddef = supercall.lookup_next_definition(self.mainmodule, mclass.intro.bound_mtype)
+ var mmethoddef = supercall.lookup_next_definition(mainmodule, mtype)
table[color] = mmethoddef
end
- tables[mclass] = table
+
end
return tables
end
var tables = new HashMap[MClass, Array[nullable MPropDef]]
for mclass in mclasses do
var table = new Array[nullable MPropDef]
- # first, fill table from parents by reverse linearization order
- var parents = new Array[MClass]
- if mainmodule.flatten_mclass_hierarchy.has(mclass) then
- parents = mclass.in_hierarchy(mainmodule).greaters.to_a
- self.mainmodule.linearize_mclasses(parents)
- end
- for parent in parents do
- if parent == mclass then continue
- for mproperty in self.mainmodule.properties(parent) do
- if not mproperty isa MAttribute then continue
- var color = attr_colors[mproperty]
- if table.length <= color then
- for i in [table.length .. color[ do
- table[i] = null
- end
- end
- for mpropdef in mproperty.mpropdefs do
- if mpropdef.mclassdef.mclass == parent then
- table[color] = mpropdef
- end
- end
- end
- end
+ tables[mclass] = table
- # then override with local properties
- for mproperty in self.mainmodule.properties(mclass) do
+ var mproperties = self.mainmodule.properties(mclass)
+ var mtype = mclass.intro.bound_mtype
+
+ for mproperty in mproperties do
if not mproperty isa MAttribute then continue
+ if not attr_colors.has_key(mproperty) then continue
var color = attr_colors[mproperty]
if table.length <= color then
for i in [table.length .. color[ do
table[i] = null
end
end
- for mpropdef in mproperty.mpropdefs do
- if mpropdef.mclassdef.mclass == mclass then
- table[color] = mpropdef
- end
- end
+ table[color] = mproperty.lookup_first_definition(mainmodule, mtype)
end
- tables[mclass] = table
end
return tables
end
# resolution table (for receiver)
if is_live then
- var mclass_type = mtype
- if mclass_type isa MNullableType then mclass_type = mclass_type.mtype
+ var mclass_type = mtype.as_notnullable
assert mclass_type isa MClassType
if resolution_tables[mclass_type].is_empty then
v.add_decl("NULL, /*NO RESOLUTIONS*/")
fun compile_type_resolution_table(mtype: MType) do
- var mclass_type: MClassType
- if mtype isa MNullableType then
- mclass_type = mtype.mtype.as(MClassType)
- else
- mclass_type = mtype.as(MClassType)
- end
+ var mclass_type = mtype.as_notnullable.as(MClassType)
# extern const struct resolution_table_X resolution_table_X
self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};")
v.require_declaration("class_{c_name}")
v.add("{res}->class = &class_{c_name};")
self.generate_init_attr(v, res, mtype)
+ v.set_finalizer res
v.add("return {res};")
end
v.add("\}")
v.add_abort("type null")
v.add("\}")
v.add("if({t}->table_size == 0) \{")
- v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", {t}->name);")
+ v.add("PRINT_ERROR(\"Insantiation of a dead type: %s\\n\", {t}->name);")
v.add_abort("type dead")
v.add("\}")
end
redef fun compile_nitni_structs
do
- self.header.add_decl("struct nitni_instance \{struct instance *value;\};")
+ self.header.add_decl """
+struct nitni_instance \{
+ struct nitni_instance *next,
+ *prev; /* adjacent global references in global list */
+ int count; /* number of time this global reference has been marked */
+ struct instance *value;
+\};
+"""
+ super
end
-
+
redef fun finalize_ffi_for_module(mmodule)
do
var old_module = self.mainmodule
var res = self.new_var(mtype)
if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
- self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
return res
end
self.require_declaration("BOX_{valtype.c_name}")
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
return res
- else if value.mtype.ctype == "void*" and mtype.ctype == "void*" then
+ else if (value.mtype.ctype == "void*" and mtype.ctype == "void*") or
+ (value.mtype.ctype == "char*" and mtype.ctype == "void*") or
+ (value.mtype.ctype == "void*" and mtype.ctype == "char*") then
return value
else
# Bad things will appen!
var res = self.new_var(mtype)
self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
- self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
return res
end
end
do
var rta = compiler.runtime_type_analysis
var recv = args.first.mtype
- if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null then
+ var mmethod = callsite.mproperty
+ # TODO: Inlining of new-style constructors
+ if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
var tgs = rta.live_targets(callsite)
if tgs.length == 1 then
# DIRECT CALL
- var mmethod = callsite.mproperty
self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), args)
var res0 = before_send(mmethod, args)
var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
do
var res: nullable RuntimeVariable = null
var recv = arguments.first
- var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value or mmethod.name == "==" or mmethod.name == "!="
+ var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or mmethod.name == "==" or mmethod.name == "!="
var maybenull = recv.mcasttype isa MNullableType and consider_null
if maybenull then
self.add("if ({recv} == NULL) \{")
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("PRINT_ERROR(\"Resolution of a dead open type: %s\\n\", \"{mtype.to_s.escape_to_c}\");")
self.add_abort("open type dead")
self.add("\}")
end
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("PRINT_ERROR(\"Try to cast on a dead cast type: %s\\n\", {t}->name);")
add_abort("cast type dead")
add("\}")
end
self.add("count_type_test_resolved_{tag}++;")
end
else
- self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
end
# check color is in table
fun can_be_primitive(value: RuntimeVariable): Bool
do
- var t = value.mcasttype
- if t isa MNullableType then t = t.mtype
+ var t = value.mcasttype.as_notnullable
if not t isa MClassType then return false
var k = t.mclass.kind
return k == interface_kind or t.ctype != "val*"
return res
end
- fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
+ redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
do
var mtype = self.get_class("NativeArray").get_mtype([elttype])
self.require_declaration("NEW_{mtype.mclass.c_name}")
return
else if pname == "copy_to" then
var recv1 = "((struct instance_{nclass.c_instance_name}*){arguments[1]})->values"
- self.add("memcpy({recv1}, {recv}, {arguments[2]}*sizeof({elttype.ctype}));")
+ self.add("memmove({recv1}, {recv}, {arguments[2]}*sizeof({elttype.ctype}));")
return
end
end