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)
+ # For now, we always use perfect hashing for subtyping test
+ return inter_is_subtype_ph(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 `{
+ private fun inter_is_subtype_ph(id: Int, mask:Int, vtable: Pointer): Bool `{
// hv is the position in hashtable
int hv = id & mask;
return *offset == id;
`}
+ # Subtyping test with Cohen test (direct access)
+ private fun inter_is_subtype_sst(id: Int, position: Int, vtable: Pointer): Bool `{
+ // Direct access to the position given in parameter
+ int tableid = (long unsigned int)((long int *)vtable)[position];
+
+ return id == tableid;
+ `}
+
# Redef init_instance to simulate the loading of a class
redef fun init_instance(recv: Instance)
do
var ret = send_commons(mproperty, args, mtype)
if ret != null then return ret
- var propdef = method_dispatch(mproperty, recv.vtable.as(not null))
+ var propdef = method_dispatch(mproperty, recv.vtable.as(not null), recv)
return self.call(propdef, args)
end
# Method dispatch, for a given global method `mproperty`
# returns the most specific local method in the class corresponding to `vtable`
- private fun method_dispatch(mproperty: MMethod, vtable: VTable): MMethodDef
+ private fun method_dispatch(mproperty: MMethod, vtable: VTable, recv: Instance): MMethodDef
do
- return method_dispatch_ph(vtable.internal_vtable, vtable.mask,
+ if mproperty.intro_mclassdef.mclass.positions_methods[recv.mtype.as(MClassType).mclass] != -1 then
+ return method_dispatch_sst(vtable.internal_vtable, mproperty.absolute_offset)
+ else
+ return method_dispatch_ph(vtable.internal_vtable, vtable.mask,
mproperty.intro_mclassdef.mclass.vtable.id, mproperty.offset)
+ end
end
# Execute a method dispatch with perfect hashing
return propdef;
`}
+ # Execute a method dispatch with direct access and return the appropriate `MMethodDef`
+ # `vtable` : Pointer to the internal pointer of the class
+ # `absolute_offset` : Absolute offset from the beginning of the virtual table
+ private fun method_dispatch_sst(vtable: Pointer, absolute_offset: Int): MMethodDef `{
+ // pointer+2 is the position where methods are
+ // Add the offset of property and get the method implementation
+ MMethodDef propdef = (MMethodDef)((long int *)vtable)[absolute_offset];
+
+ return propdef;
+ `}
+
# Return the value of the attribute `mproperty` for the object `recv`
redef fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
do
# True when the class is effectively loaded by the vm, false otherwise
var loaded: Bool = false
+ # Color for Cohen subtyping test : the absolute position of the id
+ # of this class in virtual tables
+ var color: Int
+
# For each loaded subclass, keep the position of the group of attributes
# introduced by self class in the object
var positions_attributes: HashMap[MClass, Int] = new HashMap[MClass, Int]
# Absolute offset of attribute from the beginning of the attributes table
var offset_attributes = 0
- # Absolute offset of method from the beginning of the methods table
- var offset_methods = 0
+
+ # Absolute offset of method from the beginning of the methods table,
+ # is initialize to 3 because the first position is empty in the virtual table
+ # and the second and third are respectively class id and delta
+ var offset_methods = 3
# The previous element in `superclasses`
var previous_parent: nullable MClass = null
offset_attributes += attributes
offset_methods += methods
+ offset_methods += 2 # Because each block starts with an id and the delta
end
# When all super-classes have their identifiers and vtables, allocate current one
allocate_vtable(v, ids, nb_methods, nb_attributes, offset_attributes, offset_methods)
loaded = true
+ # Set the absolute position of the identifier of this class in the virtual table
+ color = offset_methods - 2
+
# The virtual table now needs to be filled with pointer to methods
superclasses.add(self)
for cl in superclasses do
private fun superclasses_ordering(v: VirtualMachine): Array[MClass]
do
var superclasses = new Array[MClass]
- superclasses.add_all(ancestors)
+
+ # Add all superclasses of `self`
+ superclasses.add_all(self.in_hierarchy(v.mainmodule).greaters)
var res = new Array[MClass]
if superclasses.length > 1 then