import abstract_compiler
import layout_builders
import rapid_type_analysis
-import collect_super_sends
import compiler_ffi
# Add separate compiler specific options
# --no-shortcut-equate
var opt_no_shortcut_equate: OptionBool = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
# --inline-coloring-numbers
- var opt_inline_coloring_numbers: OptionBool = new OptionBool("Inline colors and ids", "--inline-coloring-numbers")
+ var opt_inline_coloring_numbers: OptionBool = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
+ # --inline-some-methods
+ var opt_inline_some_methods: OptionBool = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
+ # --direct-call-monomorph
+ var opt_direct_call_monomorph: OptionBool = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
# --use-naive-coloring
var opt_bm_typing: OptionBool = new OptionBool("Colorize items incrementaly, used to simulate binary matrix typing", "--bm-typing")
# --use-mod-perfect-hashing
self.option_context.add_option(self.opt_no_inline_intern)
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)
+ self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph)
self.option_context.add_option(self.opt_bm_typing)
self.option_context.add_option(self.opt_phmod_typing)
self.option_context.add_option(self.opt_phand_typing)
self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
write_and_make(compiler)
end
+
+ # Count number of invocations by VFT
+ private var nb_invok_by_tables = 0
+ # Count number of invocations by direct call
+ private var nb_invok_by_direct = 0
+ # Count number of invocations by inlining
+ private var nb_invok_by_inline = 0
end
# Singleton that store the knowledge about the separate compilation process
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)
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
if self.modelbuilder.toolcontext.opt_tables_metrics.value then
display_sizes
end
+
+ var tc = self.modelbuilder.toolcontext
+ tc.info("# implementation of method invocation",2)
+ var nb_invok_total = modelbuilder.nb_invok_by_tables + modelbuilder.nb_invok_by_direct + modelbuilder.nb_invok_by_inline
+ tc.info("total number of invocations: {nb_invok_total}",2)
+ tc.info("invocations by VFT send: {modelbuilder.nb_invok_by_tables} ({div(modelbuilder.nb_invok_by_tables,nb_invok_total)}%)",2)
+ tc.info("invocations by direct call: {modelbuilder.nb_invok_by_direct} ({div(modelbuilder.nb_invok_by_direct,nb_invok_total)}%)",2)
+ tc.info("invocations by inlining: {modelbuilder.nb_invok_by_inline} ({div(modelbuilder.nb_invok_by_inline,nb_invok_total)}%)",2)
end
fun display_sizes
end
end
+ redef fun compile_callsite(callsite, args)
+ do
+ var rta = compiler.runtime_type_analysis
+ var recv = args.first.mtype
+ if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and recv isa MClassType 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)
+ return call(tgs.first, recv, args)
+ end
+ end
+ return super
+ end
redef fun send(mmethod, arguments)
do
self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
do
+ compiler.modelbuilder.nb_invok_by_tables += 1
+
assert arguments.length == mmethod.intro.msignature.arity + 1 else debug("Invalid arity for {mmethod}. {arguments.length} arguments given.")
var res: nullable RuntimeVariable
res = self.new_var(ret)
end
- if self.compiler.modelbuilder.mpropdef2npropdef.has_key(mmethoddef) and
- self.compiler.modelbuilder.mpropdef2npropdef[mmethoddef] isa AInternMethPropdef and
- not compiler.modelbuilder.toolcontext.opt_no_inline_intern.value then
+ if (mmethoddef.is_intern and not compiler.modelbuilder.toolcontext.opt_no_inline_intern.value) or
+ (compiler.modelbuilder.toolcontext.opt_inline_some_methods.value and mmethoddef.can_inline(self)) then
+ compiler.modelbuilder.nb_invok_by_inline += 1
var frame = new Frame(self, mmethoddef, recvtype, arguments)
frame.returnlabel = self.get_name("RET_LABEL")
frame.returnvar = res
var old_frame = self.frame
self.frame = frame
- self.add("\{ /* Inline {mmethoddef} ({arguments.join(",")}) */")
+ self.add("\{ /* Inline {mmethoddef} ({arguments.join(",")}) on {arguments.first.inspect} */")
mmethoddef.compile_inside_to_c(self, arguments)
self.add("{frame.returnlabel.as(not null)}:(void)0;")
self.add("\}")
self.frame = old_frame
return res
end
+ compiler.modelbuilder.nb_invok_by_direct += 1
# Autobox arguments
self.adapt_signature(mmethoddef, arguments)
self.require_declaration(mmethoddef.c_name)
if res == null then
- self.add("{mmethoddef.c_name}({arguments.join(", ")});")
+ self.add("{mmethoddef.c_name}({arguments.join(", ")}); /* Direct call {mmethoddef} on {arguments.first.inspect}*/")
return null
else
self.add("{res} = {mmethoddef.c_name}({arguments.join(", ")});")
# Check for Uninitialized attribute
if not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then
- self.add("if ({res} == NULL) \{")
+ self.add("if (unlikely({res} == NULL)) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
end
# Check for Uninitialized attribute
if ret.ctype == "val*" and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then
- self.add("if ({res} == NULL) \{")
+ self.add("if (unlikely({res} == NULL)) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
end