Last week benches shows some failures on some options due to recent commits.
This PR add a `--fast --fast` option that test only `hello_world` so it could be used in continuous integration to test the various meaningful combination of compiling options.
Moreover, the script is simplified to be more simple to use and extends with new options or combination of options,
Pull-Request: #1217
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
redef fun execute
do
super
- stream_out = new FileWriter.from_fd(data.in_fd)
+ var out = new FileWriter.from_fd(data.in_fd)
+ out.set_buffering_mode(0, sys.buffer_mode_none)
+ stream_out = out
end
end
else
for i in s.substrings do write_native(i.to_cstring, i.length)
end
- _file.flush
end
redef fun close
end
end
+redef class NativeArray[E]
+ # Join all the elements using `to_s`
+ #
+ # REQUIRE: `self isa NativeArray[String]`
+ # REQUIRE: all elements are initialized
+ fun native_to_s: String
+ do
+ assert self isa NativeArray[String]
+ var l = length
+ var na = self
+ var i = 0
+ var sl = 0
+ var mypos = 0
+ while i < l do
+ sl += na[i].length
+ i += 1
+ mypos += 1
+ end
+ var ns = new NativeString(sl + 1)
+ ns[sl] = '\0'
+ i = 0
+ var off = 0
+ while i < mypos do
+ var tmp = na[i]
+ var tpl = tmp.length
+ if tmp isa FlatString then
+ tmp.items.copy_to(ns, tpl, tmp.index_from, off)
+ off += tpl
+ else
+ for j in tmp.substrings do
+ var s = j.as(FlatString)
+ var slen = s.length
+ s.items.copy_to(ns, slen, s.index_from, off)
+ off += slen
+ end
+ end
+ i += 1
+ end
+ return ns.to_s_with_length(sl)
+ end
+end
+
redef class Map[K,V]
# Concatenate couple of 'key value'.
# key and value are separated by `couple_sep`.
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
fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) is abstract
+ # Return an element of a native array.
+ # The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
+ fun native_array_get(native_array: RuntimeVariable, index: Int): RuntimeVariable is abstract
+
+ # Store an element in a native array.
+ # The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
+ fun native_array_set(native_array: RuntimeVariable, index: Int, value: RuntimeVariable) is abstract
+
# Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
# This method is used to manage varargs in signatures and returns the real array
# of runtime variables to use in the call.
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
redef class ASuperstringExpr
redef fun expr(v)
do
- var array = new Array[RuntimeVariable]
+ var type_string = mtype.as(not null)
+
+ # Collect elements of the superstring
+ var array = new Array[AExpr]
for ne in self.n_exprs do
+ # Drop literal empty string.
+ # They appears in things like "{a}" that is ["", a, ""]
if ne isa AStringFormExpr and ne.value == "" then continue # skip empty sub-strings
- var i = v.expr(ne, null)
- array.add(i)
+ array.add(ne)
end
- var a = v.array_instance(array, v.object_type)
- var res = v.send(v.get_property("to_s", a.mtype), [a])
+
+ # Store the allocated native array in a static variable
+ # For reusing later
+ var varonce = v.get_name("varonce")
+ v.add("if (unlikely({varonce}==NULL)) \{")
+
+ # The native array that will contains the elements to_s-ized.
+ # For fast concatenation.
+ var a = v.native_array_instance(type_string, v.int_instance(array.length))
+
+ v.add_decl("static {a.mtype.ctype} {varonce};")
+
+ # Pre-fill the array with the literal string parts.
+ # So they do not need to be filled again when reused
+ for i in [0..array.length[ do
+ var ne = array[i]
+ if not ne isa AStringFormExpr then continue
+ var e = v.expr(ne, null)
+ v.native_array_set(a, i, e)
+ end
+
+ v.add("\} else \{")
+ # Take the native-array from the store.
+ # The point is to prevent that some recursive execution use (and corrupt) the same native array
+ # WARNING: not thread safe! (FIXME?)
+ v.add("{a} = {varonce};")
+ v.add("{varonce} = NULL;")
+ v.add("\}")
+
+ # Stringify the elements and put them in the native array
+ var to_s_method = v.get_property("to_s", v.object_type)
+ for i in [0..array.length[ do
+ var ne = array[i]
+ if ne isa AStringFormExpr then continue
+ var e = v.expr(ne, null)
+ # Skip the `to_s` if the element is already a String
+ if not e.mcasttype.is_subtype(v.compiler.mainmodule, null, type_string) then
+ e = v.send(to_s_method, [e]).as(not null)
+ end
+ v.native_array_set(a, i, e)
+ end
+
+ # Fast join the native string to get the result
+ var res = v.send(v.get_property("native_to_s", a.mtype), [a])
+
+ # We finish to work with the native array,
+ # so store it so that it can be reused
+ v.add("{varonce} = {a};")
return res
end
end
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
+ redef fun native_array_get(nat, i)
+ do
+ var recv = "((struct {nat.mcasttype.c_name}*){nat})->values"
+ var ret_type = nat.mcasttype.as(MClassType).arguments.first
+ return self.new_expr("{recv}[{i}]", ret_type)
+ end
+
+ redef fun native_array_set(nat, i, val)
+ do
+ var recv = "((struct {nat.mcasttype.c_name}*){nat})->values"
+ self.add("{recv}[{i}]={val};")
+ end
+
redef fun calloc_array(ret_type, arguments)
do
self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type))
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)
+ redef fun native_array_get(nat, i)
+ do
+ var nclass = mmodule.native_array_class
+ var recv = "((struct instance_{nclass.c_name}*){nat})->values"
+ # Because the objects are boxed, return the box to avoid unnecessary (or broken) unboxing/reboxing
+ var res = self.new_expr("{recv}[{i}]", compiler.mainmodule.object_type)
+ return res
+ end
+
+ redef fun native_array_set(nat, i, val)
do
- var mclass = self.get_class("ArrayCapable")
- var ft = mclass.mparameters.first
- var res = self.native_array_instance(ft, arguments[1])
- self.ret(res)
+ var nclass = mmodule.native_array_class
+ var recv = "((struct instance_{nclass.c_name}*){nat})->values"
+ self.add("{recv}[{i}]={val};")
end
fun link_unresolved_type(mclassdef: MClassDef, mtype: MType) do
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]))
+ var nattype = mmodule.native_array_type(object_type)
+ v.add_type(nattype)
var prop = v.get_method(arraytype, "join")
v.add_monomorphic_send(arraytype, prop)
var prop2 = v.get_method(arraytype, "with_native")
v.add_monomorphic_send(arraytype, prop2)
+ v.add_monomorphic_send(nattype, v.get_method(nattype, "native_to_s"))
end
end
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
+++ /dev/null
-alt/error_needed_method_alt4.nit:49,10--14: Fatal Error: NativeString must have a property named to_s_with_length.