X-Git-Url: http://nitlanguage.org diff --git a/src/vm.nit b/src/vm.nit index 754b8ec..3807ab7 100644 --- a/src/vm.nit +++ b/src/vm.nit @@ -17,7 +17,7 @@ # Implementation of the Nit virtual machine module vm -intrude import naive_interpreter +import interpreter::naive_interpreter import model_utils import perfect_hashing @@ -28,7 +28,7 @@ redef class ModelBuilder self.toolcontext.info("*** NITVM STARTING ***", 1) var interpreter = new VirtualMachine(self, mainmodule, arguments) - init_naive_interpreter(interpreter, mainmodule) + interpreter.start(mainmodule) var time1 = get_time self.toolcontext.info("*** NITVM STOPPING : {time1-time0} ***", 2) @@ -44,6 +44,16 @@ class VirtualMachine super NaiveInterpreter # Handles memory and garbage collection var memory_manager: MemoryManager = new MemoryManager + # The unique instance of the `MInit` value + var initialization_value: Instance + + init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String]) + do + super + var init_type = new MInitType(mainmodule.model) + initialization_value = new MutableInstance(init_type) + end + # Subtyping test for the virtual machine redef fun is_subtype(sub, sup: MType): Bool do @@ -71,7 +81,7 @@ class VirtualMachine super NaiveInterpreter if sup isa MParameterType or sup isa MVirtualType then return sub == sup end - + if sub isa MParameterType or sub isa MVirtualType then sub = sub.anchor_to(mainmodule, anchor) # Manage the second layer of null/nullable @@ -96,7 +106,6 @@ class VirtualMachine super NaiveInterpreter # Sub can be discovered inside a Generic type during the subtyping test if not sub.mclass.loaded then create_class(sub.mclass) - if anchor == null then anchor = sub if sup isa MGenericType then var sub2 = sub.supertype_to(mainmodule, anchor, sup.mclass) assert sub2.mclass == sup.mclass @@ -124,11 +133,11 @@ class VirtualMachine super NaiveInterpreter // Follow the pointer to somewhere in the vtable long unsigned int *offset = (long unsigned int*)(((long int *)vtable)[-hv]); - + // If the pointed value is corresponding to the identifier, the test is true, otherwise false return *offset == id; `} - + # Redef init_instance to simulate the loading of a class redef fun init_instance(recv: Instance) do @@ -137,81 +146,87 @@ class VirtualMachine super NaiveInterpreter recv.vtable = recv.mtype.as(MClassType).mclass.vtable assert(recv isa MutableInstance) - - recv.internal_attributes = init_internal_attributes(null_instance, recv.mtype.as(MClassType).mclass.cached_attributes.length) + recv.internal_attributes = init_internal_attributes(initialization_value, recv.mtype.as(MClassType).mclass.all_mattributes(mainmodule, none_visibility).length) super end - + # Initialize the internal representation of an object (its attribute values) - private fun init_internal_attributes(null_instance: Instance, size: Int): Pointer + # `init_instance` is the initial value of attributes + private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer import Array[Instance].length, Array[Instance].[] `{ - + Instance* attributes = malloc(sizeof(Instance) * size); int i; for(i=0; i 1 then + # Starting at self + var ordering = self.dfs(v, res) + + return ordering + else + # There is no super-class, self is Object + return superclasses + end + end + + # A kind of Depth-First-Search for superclasses ordering + # `v` : the current executed instance of VirtualMachine + # `res` : Result Array, ie current superclasses ordering + private fun dfs(v: VirtualMachine, res: Array[MClass]): Array[MClass] + do + # Add this class at the beginning + res.insert(self, 0) + + var direct_parents = self.in_hierarchy(v.mainmodule).direct_greaters.to_a + + if direct_parents.length > 1 then + # Prefix represents the class which has the most properties + # we try to choose it in first to reduce the number of potential recompilations + var prefix = null + var max = -1 + for cl in direct_parents do + # If we never have visited this class + if not res.has(cl) then + var properties_length = cl.all_mproperties(v.mainmodule, none_visibility).length + if properties_length > max then + max = properties_length + prefix = cl + end + end + end + + if prefix != null then + # Add the prefix class ordering at the beginning of our sequence + var prefix_res = new Array[MClass] + prefix_res = prefix.dfs(v, prefix_res) + + # Then we recurse on other classes + for cl in direct_parents do + if cl != prefix then + res = new Array[MClass] + res = cl.dfs(v, res) + + for cl_res in res do + if not prefix_res.has(cl_res) then prefix_res.push(cl_res) + end + end + end + res = prefix_res + end + + res.push(self) + else + if direct_parents.length > 0 then + res = direct_parents.first.dfs(v, res) + end + end + + if not res.has(self) then res.push(self) + + return res + end + + # Update positions of self class in `parent` + # `attributes_offset`: absolute offset of introduced attributes + # `methods_offset`: absolute offset of introduced methods + private fun update_positions(attributes_offsets: Int, methods_offset:Int, parent: MClass) + do + parent.positions_attributes[self] = attributes_offsets + parent.positions_methods[self] = methods_offset + end end redef class MAttribute @@ -348,11 +484,34 @@ end # Redef MutableInstance to improve implementation of attributes in objects redef class MutableInstance - + # C-array to store pointers to attributes of this Object var internal_attributes: Pointer end +# Is the type of the initial value inside attributes +class MInitType + super MType + + redef var model: Model + protected init(model: Model) + do + self.model = model + end + + redef fun to_s do return "InitType" + redef fun as_nullable do return self + redef fun need_anchor do return false + redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self + redef fun can_resolve_for(mtype, anchor, mmodule) do return true + + redef fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef] + + redef fun collect_mclasses(mmodule) do return new HashSet[MClass] + + redef fun collect_mtypes(mmodule) do return new HashSet[MClassType] +end + # A VTable contains the virtual method table for the dispatch # and informations to perform subtyping tests class VTable @@ -377,7 +536,7 @@ end class MemoryManager # Allocate and fill a virtual table - fun init_vtable(ids: Array[Int], nb_methods: Array[Int], nb_attributes: Array[Int], mask: Int): Pointer + fun init_vtable(ids: Array[Int], nb_methods: Array[Int], nb_attributes: Array[Int], mask: Int): Pointer do # Allocate in C current virtual table var res = intern_init_vtable(ids, nb_methods, nb_attributes, mask) @@ -386,7 +545,7 @@ class MemoryManager end # Construct virtual tables with a bi-dimensional layout - private fun intern_init_vtable(ids: Array[Int], nb_methods: Array[Int], deltas: Array[Int], mask: Int): Pointer + private fun intern_init_vtable(ids: Array[Int], nb_methods: Array[Int], deltas: Array[Int], mask: Int): Pointer import Array[Int].length, Array[Int].[] `{ // Allocate and fill current virtual table @@ -396,7 +555,7 @@ class MemoryManager for(i = 0; i