# returns the most specific local method in the class corresponding to `vtable`
private fun method_dispatch(mproperty: MMethod, vtable: VTable, recv: Instance): MMethodDef
do
- if mproperty.intro_mclassdef.mclass.positions_methods[recv.mtype.as(MClassType).mclass] != -1 then
- return method_dispatch_sst(vtable.internal_vtable, mproperty.absolute_offset)
+ var position = recv.mtype.as(MClassType).mclass.get_position_methods(mproperty.intro_mclassdef.mclass)
+ if position > 0 then
+ return method_dispatch_sst(vtable.internal_vtable, mproperty.offset + position)
else
return method_dispatch_ph(vtable.internal_vtable, vtable.mask,
mproperty.intro_mclassdef.mclass.vtable.id, mproperty.offset)
assert recv isa MutableInstance
var i: Instance
-
- if mproperty.intro_mclassdef.mclass.positions_attributes[recv.mtype.as(MClassType).mclass] != -1 then
+ var position = recv.mtype.as(MClassType).mclass.get_position_attributes(mproperty.intro_mclassdef.mclass)
+ if position > 0 then
# if this attribute class has an unique position for this receiver, then use direct access
- i = read_attribute_sst(recv.internal_attributes, mproperty.absolute_offset)
+ i = read_attribute_sst(recv.internal_attributes, position + mproperty.offset)
else
# Otherwise, read the attribute value with perfect hashing
var id = mproperty.intro_mclassdef.mclass.vtable.id
assert recv isa MutableInstance
# Replace the old value of mproperty in recv
- if mproperty.intro_mclassdef.mclass.positions_attributes[recv.mtype.as(MClassType).mclass] != -1 then
+ var position = recv.mtype.as(MClassType).mclass.get_position_attributes(mproperty.intro_mclassdef.mclass)
+ if position > -1 then
# if this attribute class has an unique position for this receiver, then use direct access
- write_attribute_sst(recv.internal_attributes, mproperty.absolute_offset, value)
+ write_attribute_sst(recv.internal_attributes, position + mproperty.offset, value)
else
# Otherwise, use perfect hashing to replace the old value
var id = mproperty.intro_mclassdef.mclass.vtable.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
+ # For superclasses which have a non-invariant position, keep their position in attribute table
var positions_attributes: HashMap[MClass, Int] = new HashMap[MClass, Int]
- # For each loaded subclass, keep the position of the group of methods
- # introduced by self class in the vtable
+ # For superclasses which have a non-invariant position, keep their position in virtual table
var positions_methods: HashMap[MClass, Int] = new HashMap[MClass, Int]
- # The `MAttribute` this class introduced
- var intro_mattributes = new Array[MAttribute]
+ # The position of the class' block in virtual table,
+ # the position is set to -1 when the invariant position is no longer satisfied
+ var position_attributes: Int
- # The `MMethod` this class introduced
- var intro_mmethods = new Array[MMethod]
+ # The position of the class' block in attribute table
+ # the position is set to -1 when the invariant position is no longer satisfied
+ var position_methods: Int
# The chosen prefix for this class.
# The prefix is the direct superclass which has the most properties,
# The linear extension of all superclasses with the prefix rule
var ordering: Array[MClass]
+ # The `MAttribute` this class introduced
+ var intro_mattributes = new Array[MAttribute]
+
+ # The `MMethod` this class introduced
+ var intro_mmethods = new Array[MMethod]
+
# All `MAttribute` this class contains
var mattributes = new Array[MAttribute]
nb_methods.push(methods)
nb_attributes.push(attributes)
- # Update `positions_attributes` and `positions_methods` in `parent`.
- # If the position is invariant for this parent, store this position
- # else store a special value (-1)
- var pos_attr = -1
- var pos_meth = -1
-
- parent.update_positions(pos_attr, pos_meth, self)
+ # If the class is in the suffix part of the order
+ if i > prefix_index then
+ moved_class_attributes(vm, ordering[i], offset_attributes)
+ moved_class_methods(vm, ordering[i], offset_methods)
+ end
offset_attributes += attributes
offset_methods += methods
offset_methods += 2 # Because each block starts with an id and the delta
end
+ # Recopy the position tables of the prefix in `self`
+ for key, value in prefix.positions_methods do
+ positions_methods[key] = value
+ end
+
+ for key, value in prefix.positions_attributes do
+ positions_attributes[key] = value
+ end
+
# When all super-classes have their identifiers and vtables, allocate current one
allocate_vtable(vm, 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
ordering.add(self)
for cl in ordering do
nb_attributes_total.add_all(nb_attributes)
nb_attributes_total.push(nb_introduced_attributes)
+ # Set the color for subtyping test of this class
+ color = offset_methods - 2
+
# Save the offsets of self class
- update_positions(offset_attributes, offset_methods, self)
+ position_attributes = offset_attributes
+ position_methods = offset_methods
# Since we have the number of attributes for each class, calculate the delta
var deltas = calculate_delta(nb_attributes_total)
return res
end
- # Update positions of the class `cl`
- # * `attributes_offset`: absolute offset of introduced attributes
- # * `methods_offset`: absolute offset of introduced methods
- private fun update_positions(attributes_offsets: Int, methods_offset:Int, cl: MClass)
+ # This method is called when `current_class` class is moved in virtual table of `self`
+ # *`vm` Running instance of the virtual machine
+ # *`current_class` The class which was moved in `self` structures
+ # *`offset` The offset of block of methods of `current_class` in `self`
+ fun moved_class_methods(vm: VirtualMachine, current_class: MClass, offset: Int)
+ do
+ # `current_class` was moved in `self` method table
+ if current_class.position_methods > 0 then
+ # The invariant position is no longer satisfied
+ current_class.positions_methods[current_class] = current_class.position_methods
+ current_class.position_methods = - current_class.position_methods
+ else
+ # The class has already several positions and an update is needed
+ current_class.positions_methods[current_class] = -current_class.positions_methods[current_class]
+
+ for sub in ordering do
+ if sub == current_class then continue
+
+ var super_id = current_class.vtable.id
+ var mask = sub.vtable.mask
+
+ if vm.inter_is_subtype_ph(super_id, mask, sub.vtable.internal_vtable) then
+ if not sub.positions_methods.has_key(current_class) then
+ sub.positions_methods[current_class] = current_class.position_methods
+ else
+ var old_position = sub.positions_methods[current_class]
+ if old_position > 0 then
+ # Indicate this class can not used anymore single inheritance implementation
+ sub.positions_methods[current_class] = - old_position
+ end
+ end
+ end
+ end
+ end
+
+ # Save the position of `current_class` in `self`
+ positions_methods[current_class] = offset
+ end
+
+ # This method is called when `current_class` class is moved in attribute table of `self`
+ # *`vm` Running instance of the virtual machine
+ # *`current_class` The class which was moved in `self` structures
+ # *`offset` The offset of block of attributes of `current_class` in `self`
+ fun moved_class_attributes(vm: VirtualMachine, current_class: MClass, offset: Int)
+ do
+ # `current_class` was moved in `self` attribute table
+ if not current_class.positions_attributes.has_key(current_class) then
+ # The invariant position is no longer satisfied
+ current_class.positions_attributes[current_class] = current_class.position_attributes
+ current_class.position_attributes = - current_class.position_attributes
+ else
+ # The class has already several positions and an update is needed
+ current_class.positions_attributes[current_class] = - current_class.positions_attributes[current_class]
+
+ for sub in ordering do
+ if sub == current_class then continue
+
+ var super_id = current_class.vtable.id
+ var mask = sub.vtable.mask
+
+ if vm.inter_is_subtype_ph(super_id, mask, sub.vtable.internal_vtable) then
+ if not sub.positions_methods.has_key(current_class) then
+ sub.positions_attributes[current_class] = current_class.position_attributes
+ else
+ var old_position = sub.positions_attributes[current_class]
+ if old_position > 0 then
+ # Indicate this class can not used anymore single inheritance implementation
+ sub.positions_attributes[current_class] = - old_position
+ end
+ end
+ end
+ end
+ end
+
+ # Save the position of `current_class` in `self`
+ positions_attributes[current_class] = offset
+ end
+
+ # Return the position of the method's block of class `cl` in `self` if `cl` has an invariant position in self,
+ # Otherwise return a negative position
+ fun get_position_methods(cl: MClass): Int
+ do
+ # The class has an invariant position in all subclasses
+ if cl.position_methods > 0 then return cl.position_methods
+
+ # The position has an invariant position for this class and its subclasses only
+ if positions_methods.has_key(cl) then
+ var pos = positions_methods[cl]
+ if pos > 0 then return pos
+ return -1
+ end
+
+ # No invariant position at all, the caller must use a multiple inheritance implementation
+ return -1
+ end
+
+ # Return the position of the attribute's block of class `cl` in `self` if `cl` has an invariant position in self,
+ # Otherwise return a negative position
+ fun get_position_attributes(cl: MClass): Int
do
- positions_attributes[cl] = attributes_offsets
- positions_methods[cl] = methods_offset
+ # The class has an invariant position in all subclasses
+ if cl.position_attributes > 0 then return cl.position_attributes
+
+ # The position has an invariant position for this class and its subclasses only
+ if positions_attributes.has_key(cl) then
+ var pos = positions_attributes[cl]
+ if pos > 0 then return pos
+ return -1
+ end
+
+ # No invariant position at all, the caller must use a multiple inheritance implementation
+ return -1
end
end
callsite.id, callsite.offset)
end
+ #TODO : we need recompilations here
+ callsite.status = 0
return self.call(propdef, args)
end
end
# * `recv` The receiver (The object) of the access
protected fun optimize(mproperty: MAttribute, recv: MutableInstance)
do
- if mproperty.intro_mclassdef.mclass.positions_attributes[recv.mtype.as(MClassType).mclass] != -1 then
+ var position = recv.mtype.as(MClassType).mclass.get_position_attributes(mproperty.intro_mclassdef.mclass)
+ if position > 0 then
# if this attribute class has an unique position for this receiver, then use direct access
- offset = mproperty.absolute_offset
+ offset = position + mproperty.offset
status = 1
else
# Otherwise, perfect hashing must be used
abort
end
+ #TODO : we need recompilations here
+ status = 0
+
return i
end
end
v.write_attribute_ph(recv.internal_attributes, recv.vtable.internal_vtable,
recv.vtable.mask, id, offset, i)
end
+
+ #TODO : we need recompilations here
+ status = 0
end
end
# Otherwise we must use perfect hashing
fun optimize(recv: Instance)
do
- if mproperty.intro_mclassdef.mclass.positions_methods[recv.mtype.as(MClassType).mclass] != -1 then
- offset = mproperty.absolute_offset
+ var position = recv.mtype.as(MClassType).mclass.get_position_methods(mproperty.intro_mclassdef.mclass)
+ if position > 0 then
+ offset = position + mproperty.offset
status = 1
else
offset = mproperty.offset
if not target.mclass.loaded then return
- # Try to get the position of the target type in source's structures
- var value = source.mclass.positions_methods.get_or_null(target.mclass)
-
- if value != null then
- if value != -1 then
- # Store informations for Cohen test
- position = target.mclass.color
- status = 1
- else
- # We use perfect hashing
- status = 2
- end
- end
+ # We use perfect hashing
+ status = 2
id = target.mclass.vtable.id
end
end
# Try to get the position of the target type in source's structures
var value = source.mclass.positions_methods.get_or_null(target.mclass)
- if value != null then
- if value != -1 then
- # Store informations for Cohen test
- position = target.mclass.color
- status = 1
- else
- # We use perfect hashing
- status = 2
- end
- end
+ # We use perfect hashing
+ status = 2
id = target.mclass.vtable.id
end
end