Flushing for each small element of an output made things too slow.
real (not user) time for nitc/nitc/nitc:
before: 0m7.373s
after: 0m5.901s (-20%)
Pull-Request: #1216
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
private var it: UnicodeChar
- private var is_created: Bool
+ private var is_created = false
init(s: FlatString) do from(s, 0)
# Make a new Int literal
fun make_int(value: Int): AIntExpr
do
- return new ADecIntExpr.make(value, mmodule.get_primitive_class("Int").mclass_type)
+ return new ADecIntExpr.make(value, mmodule.int_type)
end
# Make a new instatiation
self.writer = new CodeWriter(compiler.files.last)
end
- # Force to get the primitive class named `name` or abort
- fun get_class(name: String): MClass do return self.compiler.mainmodule.get_primitive_class(name)
-
# Force to get the primitive property named `name` in the instance `recv` or abort
fun get_property(name: String, recv: MType): MMethod
do
var recv
var ctype = mtype.ctype
assert mtype.mclass.name != "NativeArray"
- if ctype == "val*" then
+ if not mtype.is_c_primitive then
recv = init_instance(mtype)
else if ctype == "char*" then
recv = new_expr("NULL/*special!*/", mtype)
end
end
+ # The currently processed module
+ #
+ # alias for `compiler.mainmodule`
+ fun mmodule: MModule do return compiler.mainmodule
+
# Generate an integer value
fun int_instance(value: Int): RuntimeVariable
do
- var res = self.new_var(self.get_class("Int").mclass_type)
- self.add("{res} = {value};")
+ var t = mmodule.int_type
+ var res = new RuntimeVariable("{value.to_s}l", t, t)
+ return res
+ end
+
+ # Generate a char value
+ fun char_instance(value: Char): RuntimeVariable
+ do
+ var t = mmodule.char_type
+ var res = new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
+ return res
+ end
+
+ # Generate a float value
+ #
+ # FIXME pass a Float, not a string
+ fun float_instance(value: String): RuntimeVariable
+ do
+ var t = mmodule.float_type
+ var res = new RuntimeVariable("{value}", t, t)
return res
end
# Generate an integer value
fun bool_instance(value: Bool): RuntimeVariable
do
- var res = self.new_var(self.get_class("Bool").mclass_type)
- if value then
- self.add("{res} = 1;")
- else
- self.add("{res} = 0;")
- end
+ var s = if value then "1" else "0"
+ var res = new RuntimeVariable(s, bool_type, bool_type)
+ return res
+ end
+
+ # Generate the `null` value
+ fun null_instance: RuntimeVariable
+ do
+ var t = compiler.mainmodule.model.null_type
+ var res = new RuntimeVariable("((val*)NULL)", t, t)
return res
end
# Generate a string value
fun string_instance(string: String): RuntimeVariable
do
- var mtype = self.get_class("String").mclass_type
+ var mtype = mmodule.string_type
var name = self.get_name("varonce")
self.add_decl("static {mtype.ctype} {name};")
var res = self.new_var(mtype)
self.add("if (likely({name}!=NULL)) \{")
self.add("{res} = {name};")
self.add("\} else \{")
- var native_mtype = self.get_class("NativeString").mclass_type
+ var native_mtype = mmodule.native_string_type
var nat = self.new_var(native_mtype)
self.add("{nat} = \"{string.escape_to_c}\";")
var length = self.int_instance(string.length)
# Short name of the `ctype` to use in unions
fun ctypename: String do return "val"
+
+ # Is the associated C type a primitive one?
+ #
+ # ENSURE `result == (ctype != "val*")`
+ fun is_c_primitive: Bool do return false
end
redef class MClassType
- redef fun ctype: String
- do
+ redef var ctype is lazy do
if mclass.name == "Int" then
return "long"
else if mclass.name == "Bool" then
end
end
+ redef var is_c_primitive is lazy do return ctype != "val*"
+
redef fun ctype_extern: String
do
if mclass.kind == extern_kind then
if is_lazy then
var set
var ret = self.mpropdef.static_mtype
- var useiset = ret.ctype == "val*" and not ret isa MNullableType
+ var useiset = not ret.is_c_primitive and not ret isa MNullableType
var guard = self.mlazypropdef.mproperty
if useiset then
set = v.isset_attribute(self.mpropdef.mproperty, recv)
v.assign(res, value)
if not useiset then
- var true_v = v.new_expr("1", v.bool_type)
+ var true_v = v.bool_instance(true)
v.write_attribute(guard, arguments.first, true_v)
end
v.add("\}")
v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
if is_lazy then
var ret = self.mpropdef.static_mtype
- var useiset = ret.ctype == "val*" and not ret isa MNullableType
+ var useiset = not ret.is_c_primitive and not ret isa MNullableType
if not useiset then
- v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.new_expr("1", v.bool_type))
+ v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.bool_instance(true))
end
end
else
end
redef class AIntExpr
- redef fun expr(v) do return v.new_expr("{self.value.to_s}", self.mtype.as(not null))
+ redef fun expr(v) do return v.int_instance(self.value.as(not null))
end
redef class AFloatExpr
- redef fun expr(v) do return v.new_expr("{self.n_float.text}", self.mtype.as(not null)) # FIXME use value, not n_float
+ redef fun expr(v) do return v.float_instance("{self.n_float.text}") # FIXME use value, not n_float
end
redef class ACharExpr
- redef fun expr(v) do return v.new_expr("'{self.value.to_s.escape_to_c}'", self.mtype.as(not null))
+ redef fun expr(v) do return v.char_instance(self.value.as(not null))
end
redef class AArrayExpr
end
redef class ATrueExpr
- redef fun expr(v) do return v.new_expr("1", self.mtype.as(not null))
+ redef fun expr(v) do return v.bool_instance(true)
end
redef class AFalseExpr
- redef fun expr(v) do return v.new_expr("0", self.mtype.as(not null))
+ redef fun expr(v) do return v.bool_instance(false)
end
redef class ANullExpr
- redef fun expr(v) do return v.new_expr("NULL", self.mtype.as(not null))
+ redef fun expr(v) do return v.null_instance
end
redef class AIsaExpr
var i = v.expr(self.n_expr, null)
if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i
- if i.mtype.ctype != "val*" then return i
+ if i.mtype.is_c_primitive then return i
v.add("if (unlikely({i} == NULL)) \{")
v.add_abort("Cast failed")
self.header = new CodeWriter(file)
self.live_primitive_types = new Array[MClassType]
for t in runtime_type_analysis.live_types do
- if t.ctype != "val*" or t.mclass.name == "Pointer" then
+ if t.is_c_primitive or t.mclass.name == "Pointer" then
self.live_primitive_types.add(t)
end
end
# Init instance code (allocate and init-arguments)
for t in runtime_type_analysis.live_types do
- if t.ctype == "val*" then
+ if not t.is_c_primitive then
compiler.generate_init_instance(t)
if t.mclass.kind == extern_kind then
compiler.generate_box_instance(t)
fun generate_init_instance(mtype: MClassType)
do
assert self.runtime_type_analysis.live_types.has(mtype)
- assert mtype.ctype == "val*"
+ assert not mtype.is_c_primitive
var v = self.new_visitor
var is_native_array = mtype.mclass.name == "NativeArray"
do
if value.mtype == mtype then
return value
- else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
+ else if not value.mtype.is_c_primitive and not mtype.is_c_primitive then
return value
- else if value.mtype.ctype == "val*" then
+ else if not value.mtype.is_c_primitive then
return self.new_expr("((struct {mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
- else if mtype.ctype == "val*" then
+ else if not mtype.is_c_primitive then
var valtype = value.mtype.as(MClassType)
var res = self.new_var(mtype)
if not compiler.runtime_type_analysis.live_types.has(valtype) then
redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
do
- var ret_type = self.get_class("NativeArray").get_mtype([elttype])
+ var ret_type = mmodule.native_array_type(elttype)
ret_type = anchor(ret_type).as(MClassType)
return self.new_expr("NEW_{ret_type.c_name}({length})", ret_type)
end
end
self.add("/* send {m} on {args.first.inspect} */")
- if args.first.mtype.ctype != "val*" then
+ if args.first.mtype.is_c_primitive then
var mclasstype = args.first.mtype.as(MClassType)
if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
self.add("/* skip, no method {m} */")
var defaultpropdef: nullable MMethodDef = null
for t in types do
var propdef = m.lookup_first_definition(self.compiler.mainmodule, t)
- if propdef.mclassdef.mclass.name == "Object" and t.ctype == "val*" then
+ if propdef.mclassdef.mclass.name == "Object" and not t.is_c_primitive then
defaultpropdef = propdef
continue
end
end
self.add("/* super {m} on {args.first.inspect} */")
- if args.first.mtype.ctype != "val*" then
+ if args.first.mtype.is_c_primitive then
var mclasstype = args.first.mtype.as(MClassType)
if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
self.add("/* skip, no method {m} */")
fun bugtype(recv: RuntimeVariable)
do
- if recv.mtype.ctype != "val*" then return
+ if recv.mtype.is_c_primitive then return
self.add("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
self.add("fatal_exit(1);")
end
ta = self.resolve_for(ta, recv2)
var attr = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
if not ta isa MNullableType then
- if ta.ctype == "val*" then
+ if not ta.is_c_primitive then
self.add("{res} = ({attr} != NULL);")
else
self.add("{res} = 1; /*NOTYET isset on primitive attributes*/")
ta = self.resolve_for(ta, recv2)
var res2 = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
- if ta.ctype == "val*" then
+ if not ta.is_c_primitive then
self.add("if ({res2} == NULL) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
var res = self.new_var(bool_type)
self.add("/* isa {mtype} on {value.inspect} */")
- if value.mtype.ctype != "val*" then
+ if value.mtype.is_c_primitive then
if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
self.add("{res} = 1;")
else
redef fun is_same_type_test(value1, value2)
do
var res = self.new_var(bool_type)
- if value2.mtype.ctype == "val*" then
- if value1.mtype.ctype == "val*" then
+ if not value2.mtype.is_c_primitive then
+ if not value1.mtype.is_c_primitive then
self.add "{res} = {value1}->classid == {value2}->classid;"
else
self.add "{res} = {self.compiler.classid(value1.mtype.as(MClassType))} == {value2}->classid;"
end
else
- if value1.mtype.ctype == "val*" then
+ if not value1.mtype.is_c_primitive then
self.add "{res} = {value1}->classid == {self.compiler.classid(value2.mtype.as(MClassType))};"
else if value1.mcasttype == value2.mcasttype then
self.add "{res} = 1;"
do
var res = self.get_name("var_class_name")
self.add_decl("const char* {res};")
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
self.add "{res} = class_names[{value}->classid];"
else
self.add "{res} = class_names[{self.compiler.classid(value.mtype.as(MClassType))}];"
redef fun equal_test(value1, value2)
do
var res = self.new_var(bool_type)
- if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+ if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
var tmp = value1
value1 = value2
value2 = tmp
end
- if value1.mtype.ctype != "val*" then
+ if value1.mtype.is_c_primitive then
if value2.mtype == value1.mtype then
self.add("{res} = {value1} == {value2};")
- else if value2.mtype.ctype != "val*" then
+ else if value2.mtype.is_c_primitive then
self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
else
var mtype1 = value1.mtype.as(MClassType)
redef fun array_instance(array, elttype)
do
elttype = self.anchor(elttype)
- var arraytype = self.get_class("Array").get_mtype([elttype])
+ var arraytype = mmodule.array_type(elttype)
var res = self.init_instance(arraytype)
self.add("\{ /* {res} = array_instance Array[{elttype}] */")
- var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype]))
+ var nat = self.new_var(mmodule.native_array_type(elttype))
nat.is_exact = true
self.add("{nat} = NEW_{nat.mtype.c_name}({array.length});")
for i in [0..array.length[ do
for i in [0..mmethoddef.msignature.arity[ do
var mtype = mmethoddef.msignature.mparameters[i].mtype
if i == mmethoddef.msignature.vararg_rank then
- mtype = v.get_class("Array").get_mtype([mtype])
+ mtype = v.mmodule.array_type(mtype)
end
mtype = v.resolve_for(mtype, selfvar)
comment.append(", {mtype}")
if mclass.mclass_type.ctype_extern == "val*" then
return 0
else if mclass.kind == extern_kind and mclass.name != "NativeString" then
- return self.box_kinds[self.mainmodule.get_primitive_class("Pointer")]
+ return self.box_kinds[self.mainmodule.pointer_type.mclass]
else
return self.box_kinds[mclass]
end
var v = new_visitor
var rta = runtime_type_analysis
- var is_dead = rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" and mclass.name != "Pointer"
+ var is_dead = rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" and mclass.name != "Pointer"
v.add_decl("/* runtime class {c_name} */")
v.add_decl("\};")
end
- if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then
+ if mtype.is_c_primitive or mtype.mclass.name == "Pointer" then
# Is a primitive type or the Pointer class, not any other extern class
if mtype.is_tagged then return
do
if value.mtype == mtype then
return value
- else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
+ else if not value.mtype.is_c_primitive and not mtype.is_c_primitive then
return value
- else if value.mtype.ctype == "val*" then
+ else if not value.mtype.is_c_primitive then
if mtype.is_tagged then
if mtype.name == "Int" then
return self.new_expr("(long)({value})>>2", mtype)
end
end
return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
- else if mtype.ctype == "val*" then
+ else if not mtype.is_c_primitive then
if value.mtype.is_tagged then
if value.mtype.name == "Int" then
return self.new_expr("(val*)({value}<<2|1)", mtype)
# Thus the expression can be used as a condition.
fun extract_tag(value: RuntimeVariable): String
do
- assert value.mtype.ctype == "val*"
+ assert not value.mtype.is_c_primitive
return "((long){value}&3)" # Get the two low bits
end
# The point of the method is to work also with primitive types.
fun class_info(value: RuntimeVariable): String
do
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
if can_be_primitive(value) and not compiler.modelbuilder.toolcontext.opt_no_tag_primitives.value then
var tag = extract_tag(value)
return "({tag}?class_info[{tag}]:{value}->class)"
# The point of the method is to work also with primitive types.
fun type_info(value: RuntimeVariable): String
do
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
if can_be_primitive(value) and not compiler.modelbuilder.toolcontext.opt_no_tag_primitives.value then
var tag = extract_tag(value)
return "({tag}?type_info[{tag}]:{value}->type)"
end
redef fun send(mmethod, arguments)
do
- if arguments.first.mcasttype.ctype != "val*" then
+ if arguments.first.mcasttype.is_c_primitive then
# In order to shortcut the primitive, we need to find the most specific method
# Howverr, because of performance (no flattening), we always work on the realmainmodule
var m = self.compiler.mainmodule
redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
do
- if arguments.first.mcasttype.ctype != "val*" then
+ if arguments.first.mcasttype.is_c_primitive then
# In order to shortcut the primitive, we need to find the most specific method
# However, because of performance (no flattening), we always work on the realmainmodule
var main = self.compiler.mainmodule
self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/")
else
- if mtype.ctype == "val*" then
+ if not mtype.is_c_primitive and not mtype.is_tagged then
self.add("{res} = {recv}->attrs[{a.const_color}].val != NULL; /* {a} on {recv.inspect} */")
else
self.add("{res} = 1; /* NOT YET IMPLEMENTED: isset of primitives: {a} on {recv.inspect} */")
self.add("{res} = {recv}->attrs[{a.const_color}].{ret.ctypename}; /* {a} on {recv.inspect} */")
# Check for Uninitialized attribute
- if ret.ctype == "val*" and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
+ if not ret.is_c_primitive and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
self.add("if (unlikely({res} == NULL)) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
self.require_declaration(a.const_color)
if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
var attr = "{recv}->attrs[{a.const_color}]"
- if mtype.ctype != "val*" then
+ if mtype.is_tagged then
+ # The attribute is not primitive, thus store it as tagged
+ var tv = autobox(value, compiler.mainmodule.object_type)
+ self.add("{attr} = {tv}; /* {a} on {recv.inspect} */")
+ else if mtype.is_c_primitive then
assert mtype isa MClassType
# The attribute is primitive, thus we store it in a box
# The trick is to create the box the first time then resuse the box
do
var res = self.new_var(bool_type)
# Swap values to be symetric
- if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+ if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
var tmp = value1
value1 = value2
value2 = tmp
end
- if value1.mtype.ctype != "val*" then
+ if value1.mtype.is_c_primitive then
if value2.mtype == value1.mtype then
self.add("{res} = 1; /* is_same_type_test: compatible types {value1.mtype} vs. {value2.mtype} */")
- else if value2.mtype.ctype != "val*" then
+ else if value2.mtype.is_c_primitive then
self.add("{res} = 0; /* is_same_type_test: incompatible types {value1.mtype} vs. {value2.mtype}*/")
else
var mtype1 = value1.mtype.as(MClassType)
do
var res = self.get_name("var_class_name")
self.add_decl("const char* {res};")
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
self.add "{res} = {value} == NULL ? \"null\" : {type_info(value)}->name;"
else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind and
value.mtype.as(MClassType).name != "NativeString" then
redef fun equal_test(value1, value2)
do
var res = self.new_var(bool_type)
- if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+ if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
var tmp = value1
value1 = value2
value2 = tmp
end
- if value1.mtype.ctype != "val*" then
+ if value1.mtype.is_c_primitive then
if value2.mtype == value1.mtype then
self.add("{res} = {value1} == {value2};")
- else if value2.mtype.ctype != "val*" then
+ else if value2.mtype.is_c_primitive then
self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
else if value1.mtype.is_tagged then
self.add("{res} = ({value2} != NULL) && ({self.autobox(value2, value1.mtype)} == {value1});")
var incompatible = false
var primitive
- if t1.ctype != "val*" then
+ if t1.is_c_primitive then
primitive = t1
if t1 == t2 then
# No need to compare class
- else if t2.ctype != "val*" then
+ else if t2.is_c_primitive then
incompatible = true
else if can_be_primitive(value2) then
if t1.is_tagged then
else
incompatible = true
end
- else if t2.ctype != "val*" then
+ else if t2.is_c_primitive then
primitive = t2
if can_be_primitive(value1) then
if t2.is_tagged then
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 k == interface_kind or t.is_c_primitive
end
fun maybe_null(value: RuntimeVariable): Bool
redef fun array_instance(array, elttype)
do
- var nclass = self.get_class("NativeArray")
- var arrayclass = self.get_class("Array")
+ var nclass = mmodule.native_array_class
+ var arrayclass = mmodule.array_class
var arraytype = arrayclass.get_mtype([elttype])
var res = self.init_instance(arraytype)
self.add("\{ /* {res} = array_instance Array[{elttype}] */")
redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
do
- var mtype = self.get_class("NativeArray").get_mtype([elttype])
+ var mtype = mmodule.native_array_type(elttype)
self.require_declaration("NEW_{mtype.mclass.c_name}")
assert mtype isa MGenericType
var compiler = self.compiler
redef fun native_array_def(pname, ret_type, arguments)
do
var elttype = arguments.first.mtype
- var nclass = self.get_class("NativeArray")
+ var nclass = mmodule.native_array_class
var recv = "((struct instance_{nclass.c_name}*){arguments[0]})->values"
if pname == "[]" then
# Because the objects are boxed, return the box to avoid unnecessary (or broken) unboxing/reboxing
end
end
- redef fun calloc_array(ret_type, arguments)
- do
- var mclass = self.get_class("ArrayCapable")
- var ft = mclass.mparameters.first
- var res = self.native_array_instance(ft, arguments[1])
- self.ret(res)
- end
-
fun link_unresolved_type(mclassdef: MClassDef, mtype: MType) do
assert mtype.need_anchor
var compiler = self.compiler
for i in [0..called_signature.arity[ do
var mtype = called_signature.mparameters[i].mtype
if i == called_signature.vararg_rank then
- mtype = mmethoddef.mclassdef.mmodule.get_primitive_class("Array").get_mtype([mtype])
+ mtype = mmethoddef.mclassdef.mmodule.array_type(mtype)
end
sig.append(", {mtype.ctype} p{i}")
end
for i in [0..msignature.arity[ do
var mtype = msignature.mparameters[i].mtype
if i == msignature.vararg_rank then
- mtype = v.get_class("Array").get_mtype([mtype])
+ mtype = v.mmodule.array_type(mtype)
end
comment.append(", {mtype}")
var argvar = new RuntimeVariable("p{i}", mtype, mtype)
var selfvar = arguments.first
var ret = called_signature.return_mtype
- if mmethoddef.is_intro and recv.ctype == "val*" then
+ if mmethoddef.is_intro and not recv.is_c_primitive then
var m = mmethoddef.mproperty
var n2 = "CALL_" + m.const_color
compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
v2.add "\}"
end
- if mmethoddef.has_supercall and recv.ctype == "val*" then
+ if mmethoddef.has_supercall and not recv.is_c_primitive then
var m = mmethoddef
var n2 = "CALL_" + m.const_color
compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
return super
end
end
+
+redef class AAttrPropdef
+ redef fun init_expr(v, recv)
+ do
+ super
+ if is_lazy and v.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
+ var guard = self.mlazypropdef.mproperty
+ v.write_attribute(guard, recv, v.bool_instance(false))
+ end
+ end
+end
var rta = runtime_type_analysis
var is_dead = false # mclass.kind == abstract_kind or mclass.kind == interface_kind
- if not is_dead and rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" then
+ if not is_dead and rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" then
is_dead = true
end
v.add_decl("\}")
v.add_decl("\};")
- if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then
+ if mtype.is_c_primitive or mtype.mclass.name == "Pointer" then
#Build instance struct
self.header.add_decl("struct instance_{c_name} \{")
self.header.add_decl("const struct class *class;")
end
var class_ptr
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
class_ptr = "{value}->class->"
else
var mclass = value.mtype.as(MClassType).mclass
else if mtype isa MVirtualType then
var recv = self.frame.arguments.first
var recv_ptr
- if recv.mtype.ctype == "val*" then
+ if not recv.mtype.is_c_primitive then
recv_ptr = "{recv}->class->"
else
var mclass = recv.mtype.as(MClassType).mclass
do
var res = self.get_name("var_class_name")
self.add_decl("const char* {res};")
- if value.mtype.ctype == "val*" then
+ if not value.mtype.is_c_primitive then
self.add "{res} = {value} == NULL ? \"null\" : {value}->class->name;"
else
self.require_declaration("class_{value.mtype.c_name}")
redef fun native_array_instance(elttype, length)
do
- var nclass = self.get_class("NativeArray")
+ var nclass = mmodule.native_array_class
var mtype = nclass.get_mtype([elttype])
var res = self.new_var(mtype)
res.is_exact = true
# Return the integer instance associated with `val`.
fun int_instance(val: Int): Instance
do
- var ic = get_primitive_class("Int")
- var instance = new PrimitiveInstance[Int](ic.mclass_type, val)
+ var t = mainmodule.int_type
+ var instance = new PrimitiveInstance[Int](t, val)
init_instance_primitive(instance)
return instance
end
# Return the char instance associated with `val`.
fun char_instance(val: Char): Instance
do
- var ic = get_primitive_class("Char")
- var instance = new PrimitiveInstance[Char](ic.mclass_type, val)
+ var t = mainmodule.char_type
+ var instance = new PrimitiveInstance[Char](t, val)
init_instance_primitive(instance)
return instance
end
# Return the float instance associated with `val`.
fun float_instance(val: Float): Instance
do
- var ic = get_primitive_class("Float")
- var instance = new PrimitiveInstance[Float](ic.mclass_type, val)
+ var t = mainmodule.float_type
+ var instance = new PrimitiveInstance[Float](t, val)
init_instance_primitive(instance)
return instance
end
fun array_instance(values: Array[Instance], elttype: MType): Instance
do
assert not elttype.need_anchor
- var nat = new PrimitiveInstance[Array[Instance]](get_primitive_class("NativeArray").get_mtype([elttype]), values)
+ var nat = new PrimitiveInstance[Array[Instance]](mainmodule.native_array_type(elttype), values)
init_instance_primitive(nat)
- var mtype = get_primitive_class("Array").get_mtype([elttype])
+ var mtype = mainmodule.array_type(elttype)
var res = new MutableInstance(mtype)
self.init_instance(res)
self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
do
var val = new FlatBuffer.from(txt)
val.add('\0')
- var ic = get_primitive_class("NativeString")
- var instance = new PrimitiveInstance[Buffer](ic.mclass_type, val)
+ var t = mainmodule.native_string_type
+ var instance = new PrimitiveInstance[Buffer](t, val)
init_instance_primitive(instance)
return instance
end
# A hook to initialize a `PrimitiveInstance`
fun init_instance_primitive(recv: Instance) do end
- # Return the primitive `MClass` corresponding to the `name` given in parameter
- # `name` : name of the primitive class
- fun get_primitive_class(name: String): MClass
- do
- return mainmodule.get_primitive_class(name)
- end
-
# This function determines the correct type according to the receiver of the current propdef (self).
fun unanchor_type(mtype: MType): MType
do
if pname == "files" then
var res = new Array[Instance]
for f in str.files do res.add v.string_instance(f)
- return v.array_instance(res, v.get_primitive_class("String").mclass_type)
+ return v.array_instance(res, v.mainmodule.string_type)
end
else if pname == "calloc_string" then
return v.native_string_instance("!" * args[1].to_i)
else if pname == "set_buffering_type" then
return v.int_instance(recvval.as(PrimitiveNativeFile).set_buffering_type(args[1].to_i, args[2].to_i))
end
- else if pname == "calloc_array" then
- var recvtype = args.first.mtype.as(MClassType)
- var mtype: MType
- mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.get_primitive_class("ArrayCapable"))
- mtype = mtype.arguments.first
- var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
- var instance = new PrimitiveInstance[Array[Instance]](v.get_primitive_class("NativeArray").get_mtype([mtype]), val)
- v.init_instance_primitive(instance)
- return instance
else if pname == "native_argc" then
return v.int_instance(v.arguments.length)
else if pname == "native_argv" then
if i == null then return null
array.add(i)
end
- var i = v.array_instance(array, v.get_primitive_class("Object").mclass_type)
+ var i = v.array_instance(array, v.mainmodule.object_type)
var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
assert res != null
return res
private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null
# The primitive type `Object`, the root of the class hierarchy
- fun object_type: MClassType
- do
- var res = self.object_type_cache
- if res != null then return res
- res = self.get_primitive_class("Object").mclass_type
- self.object_type_cache = res
- return res
- end
-
- private var object_type_cache: nullable MClassType
+ var object_type: MClassType = self.get_primitive_class("Object").mclass_type is lazy
# The type `Pointer`, super class to all extern classes
var pointer_type: MClassType = self.get_primitive_class("Pointer").mclass_type is lazy
# The primitive type `Bool`
- fun bool_type: MClassType
- do
- var res = self.bool_type_cache
- if res != null then return res
- res = self.get_primitive_class("Bool").mclass_type
- self.bool_type_cache = res
- return res
- end
+ var bool_type: MClassType = self.get_primitive_class("Bool").mclass_type is lazy
+
+ # The primitive type `Int`
+ var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy
+
+ # The primitive type `Char`
+ var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy
+
+ # The primitive type `Float`
+ var float_type: MClassType = self.get_primitive_class("Float").mclass_type is lazy
+
+ # The primitive type `String`
+ var string_type: MClassType = self.get_primitive_class("String").mclass_type is lazy
+
+ # The primitive type `NativeString`
+ var native_string_type: MClassType = self.get_primitive_class("NativeString").mclass_type is lazy
+
+ # A primitive type of `Array`
+ fun array_type(elt_type: MType): MClassType do return array_class.get_mtype([elt_type])
+
+ # The primitive class `Array`
+ var array_class: MClass = self.get_primitive_class("Array") is lazy
+
+ # A primitive type of `NativeArray`
+ fun native_array_type(elt_type: MType): MClassType do return native_array_class.get_mtype([elt_type])
- private var bool_type_cache: nullable MClassType
+ # The primitive class `NativeArray`
+ var native_array_class: MClass = self.get_primitive_class("NativeArray") is lazy
# The primitive type `Sys`, the main type of the program, if any
fun sys_type: nullable MClassType
import frontend
import parser_util
import vm
-import vm_optimizations
-import variables_numbering
# Create a tool context to handle options and paths
var toolcontext = new ToolContext
module nitvm
import vm
-import vm_optimizations
-import variables_numbering
import frontend
# Create a tool context to handle options and paths
</manifest>
<!-- END_INCLUDE(manifest) -->
"""
+ manifest_file.close
### Link to png sources
# libpng is not available on Android NDK
var node = self.modelbuilder.mpropdef2node(mmethoddef)
var elttype = mmethoddef.msignature.mparameters[vararg_rank].mtype
#elttype = elttype.anchor_to(self.mainmodule, v.receiver)
- var vararg = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
+ var vararg = self.mainmodule.array_type(elttype)
v.add_type(vararg)
- var native = self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype])
+ var native = self.mainmodule.native_array_type(elttype)
v.add_type(native)
v.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg.mclass, self.mainmodule))
end
return mtype
end
- fun get_class(name: String): MClass
- do
- return analysis.mainmodule.get_primitive_class(name)
- end
-
fun get_method(recv: MType, name: String): MMethod
do
var mtype = cleanup_type(recv)
do
var mtype = self.mtype.as(MClassType)
v.add_type(mtype)
- var native = v.analysis.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype.arguments.first])
+ var native = v.analysis.mainmodule.native_array_type(mtype.arguments.first)
v.add_type(native)
mtype = v.cleanup_type(mtype).as(not null)
var prop = v.get_method(mtype, "with_native")
redef class AStringFormExpr
redef fun accept_rapid_type_visitor(v)
do
- var native = v.get_class("NativeString").mclass_type
+ var native = v.analysis.mainmodule.native_string_type
v.add_type(native)
var prop = v.get_method(native, "to_s_with_length")
v.add_monomorphic_send(native, prop)
redef class ASuperstringExpr
redef fun accept_rapid_type_visitor(v)
do
- var arraytype = v.get_class("Array").get_mtype([v.get_class("Object").mclass_type])
+ var mmodule = v.analysis.mainmodule
+ var object_type = mmodule.object_type
+ var arraytype = mmodule.array_type(object_type)
v.add_type(arraytype)
- v.add_type(v.get_class("NativeArray").get_mtype([v.get_class("Object").mclass_type]))
+ v.add_type(mmodule.native_array_type(object_type))
var prop = v.get_method(arraytype, "join")
v.add_monomorphic_send(arraytype, prop)
var prop2 = v.get_method(arraytype, "with_native")
node.full_transform_visitor(self)
end
- # Get a primitive class or display a fatal error on `location`.
- fun get_class(location: AExpr, name: String): MClass
- do
- return mmodule.get_primitive_class(name)
- end
-
# Get a primitive method or display a fatal error on `location`.
fun get_method(location: AExpr, name: String, recv: MClass): MMethod
do
# Handle all numbering operations related to local variables in the Nit virtual machine
module variables_numbering
-import vm
+import virtual_machine
redef class VirtualMachine
# limitations under the License.
# Implementation of the Nit virtual machine
-module vm
+module virtual_machine
import interpreter::naive_interpreter
import perfect_hashing
recv.vtable = recv.mtype.as(MClassType).mclass.vtable
end
- # Create a virtual table for this `MClass` if not already done
- redef fun get_primitive_class(name: String): MClass
- do
- var mclass = super
-
- if not mclass.loaded then create_class(mclass)
-
- return mclass
- end
-
# Initialize the internal representation of an object (its attribute values)
# `init_instance` is the initial value of attributes
private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Julien Pagès <julien.pages@lirmm.fr>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Entry point of all vm components
+module vm
+
+import virtual_machine
+import vm_optimizations
+import variables_numbering
# Optimization of the nitvm
module vm_optimizations
-import vm
+import virtual_machine
redef class VirtualMachine