# This file is part of NIT ( http://www.nitlanguage.org ). # # Copyright 2014 Julien Pagès # # 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. # Implementation of the Nit virtual machine module vm intrude import naive_interpreter import model_utils import perfect_hashing redef class ModelBuilder redef fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String]) do var time0 = get_time self.toolcontext.info("*** NITVM STARTING ***", 1) var interpreter = new VirtualMachine(self, mainmodule, arguments) init_naive_interpreter(interpreter, mainmodule) var time1 = get_time self.toolcontext.info("*** NITVM STOPPING : {time1-time0} ***", 2) end end # A virtual machine based on the naive_interpreter class VirtualMachine super NaiveInterpreter # Perfect hashing and perfect numbering var ph: Perfecthashing = new Perfecthashing # Handles memory and garbage collection var memory_manager: MemoryManager = new MemoryManager # Subtyping test for the virtual machine redef fun is_subtype(sub, sup: MType): Bool do var anchor = self.frame.arguments.first.mtype.as(MClassType) var sup_accept_null = false if sup isa MNullableType then sup_accept_null = true sup = sup.mtype else if sup isa MNullType then sup_accept_null = true end # Can `sub` provides null or not? # Thus we can match with `sup_accept_null` # Also discard the nullable marker if it exists if sub isa MNullableType then if not sup_accept_null then return false sub = sub.mtype else if sub isa MNullType then return sup_accept_null end # Now the case of direct null and nullable is over # An unfixed formal type can only accept itself 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 if sub isa MNullableType then if not sup_accept_null then return false sub = sub.mtype else if sub isa MNullType then return sup_accept_null end end assert sub isa MClassType # `sup` accepts only null if sup isa MNullType then return false assert sup isa MClassType # Create the sup vtable if not create if not sup.mclass.loaded then create_class(sup.mclass) # 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 for i in [0..sup.mclass.arity[ do var sub_arg = sub2.arguments[i] var sup_arg = sup.arguments[i] var res = is_subtype(sub_arg, sup_arg) if res == false then return false end return true end var super_id = sup.mclass.vtable.id var mask = sub.mclass.vtable.mask return inter_is_subtype(super_id, mask, sub.mclass.vtable.internal_vtable) end # Subtyping test with perfect hashing private fun inter_is_subtype(id: Int, mask:Int, vtable: Pointer): Bool `{ // hv is the position in hashtable int hv = id & mask; // 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 if not recv.mtype.as(MClassType).mclass.loaded then create_class(recv.mtype.as(MClassType).mclass) 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) super end # Initialize the internal representation of an object (its attribute values) private fun init_internal_attributes(null_instance: Instance, size: Int): Pointer import Array[Instance].length, Array[Instance].[] `{ Instance* attributes = malloc(sizeof(Instance) * size); int i; for(i=0; i