nitc :: vm_optimizations $ AAttrAssignExpr
The assignment of an attribute. egx._a=y
nitc :: vm_optimizations $ AAttrFormExpr
Whatever is a old-style attribute accessnitc :: vm_optimizations $ CallSite
Add informations to optimize some method callsnitc :: vm_optimizations $ VirtualMachine
A virtual machine based on the naive_interpreternitc :: vm_optimizations $ AAttrAssignExpr
The assignment of an attribute. egx._a=y
nitc :: vm_optimizations $ AAttrFormExpr
Whatever is a old-style attribute accessnitc :: vm_optimizations $ CallSite
Add informations to optimize some method callsnitc :: vm_optimizations $ VirtualMachine
A virtual machine based on the naive_interpreterSerializable::inspect
to show more useful information
nitc :: modelbuilder
more_collections :: more_collections
Highly specific, but useful, collections-related classes.serialization :: serialization_core
Abstract services to serialize Nit objects to different formatsserialize_to_json
and JsonSerializer
nitc :: toolcontext
Common command-line tool infrastructure than handle options and error messagescore :: union_find
union–find algorithm using an efficient disjoint-set data structure
# Optimization of the nitvm
module vm_optimizations
import virtual_machine
redef class VirtualMachine
# Add optimization of the method dispatch
redef fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
do
return send_optimize(callsite.as(not null), arguments)
end
# Try to have the most efficient implementation of the method dispatch
fun send_optimize(callsite: CallSite, args: Array[Instance]): nullable Instance
do
var recv = args.first
var mtype = recv.mtype
var ret = send_commons(callsite.mproperty, args, mtype)
if ret != null then return ret
if callsite.status == 0 then callsite.optimize(recv)
var propdef
if callsite.status == 1 then
propdef = method_dispatch_sst(recv.vtable.internal_vtable, callsite.offset)
else
propdef = method_dispatch_ph(recv.vtable.internal_vtable, recv.vtable.mask,
callsite.id, callsite.offset)
end
#TODO : we need recompilations here
callsite.status = 0
return self.call(propdef, args)
end
end
redef class AAttrFormExpr
# Position of the attribute in attribute table
#
# The relative position of this attribute if perfect hashing is used,
# The absolute position of this attribute if SST is used
var offset: Int
# Indicate the status of the optimization for this node
#
# 0: default value
# 1: SST (direct access) can be used
# 2: PH (multiple inheritance implementation) must be used
var status: Int = 0
# Identifier of the class which introduced the attribute
var id: Int
# Optimize this attribute access
# * `mproperty` The attribute which is accessed
# * `recv` The receiver (The object) of the access
protected fun optimize(mproperty: MAttribute, recv: MutableInstance)
do
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 = position + mproperty.offset
status = 1
else
# Otherwise, perfect hashing must be used
id = mproperty.intro_mclassdef.mclass.vtable.id
offset = mproperty.offset
status = 2
end
end
end
redef class AAttrExpr
redef fun expr(v)
do
# TODO : a workaround for now
if not v isa VirtualMachine then return super
var recv = v.expr(self.n_expr)
if recv == null then return null
if recv.mtype isa MNullType then fatal(v, "Receiver is null")
var mproperty = self.mproperty.as(not null)
assert recv isa MutableInstance
if status == 0 then optimize(mproperty, recv)
var i: Instance
if status == 1 then
# SST
i = v.read_attribute_sst(recv.internal_attributes, offset)
else
# PH
i = v.read_attribute_ph(recv.internal_attributes, recv.vtable.internal_vtable, recv.vtable.mask, id, offset)
end
# If we get a `MInit` value, throw an error
if i == v.initialization_value then
v.fatal("Uninitialized attribute {mproperty.name}")
abort
end
#TODO : we need recompilations here
status = 0
return i
end
end
redef class AAttrAssignExpr
redef fun stmt(v)
do
# TODO : a workaround for now
if not v isa VirtualMachine then
super
return
end
var recv = v.expr(self.n_expr)
if recv == null then return
if recv.mtype isa MNullType then fatal(v, "Receiver is null")
var i = v.expr(self.n_value)
if i == null then return
var mproperty = self.mproperty.as(not null)
assert recv isa MutableInstance
if status == 0 then optimize(mproperty, recv)
if status == 1 then
v.write_attribute_sst(recv.internal_attributes, offset, i)
else
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
# Add informations to optimize some method calls
redef class CallSite
# Position of the method in virtual table
#
# The relative position of this MMethod if perfect hashing is used,
# The absolute position of this MMethod if SST is used
var offset: Int
# Indicate the status of the optimization for this node
#
# 0: default value
# 1: SST (direct access) can be used
# 2: PH (multiple inheritance implementation) must be used
var status: Int = 0
# Identifier of the class which introduced the MMethod
var id: Int
# Optimize a method dispatch,
# If this method is always at the same position in virtual table, we can use direct access,
# Otherwise we must use perfect hashing
fun optimize(recv: Instance)
do
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
status = 2
end
id = mproperty.intro_mclassdef.mclass.vtable.id
end
end
redef class AIsaExpr
# Identifier of the target class type
var id: Int
# If the Cohen test is used, the position of the target id in vtable
var position: Int
# Indicate the status of the optimization for this node
#
# 0 : the default value
# 1 : this test can be implemented with direct access
# 2 : this test must be implemented with perfect hashing
var status: Int = 0
redef fun expr(v)
do
# TODO : a workaround for now
if not v isa VirtualMachine then return super
var recv = v.expr(self.n_expr)
if recv == null then return null
optimize(v, recv.mtype, self.cast_type.as(not null))
var mtype = v.unanchor_type(self.cast_type.as(not null))
# If this test can be optimized, directly call appropriate subtyping methods
if status == 1 and recv.mtype isa MClassType then
# Direct access
return v.bool_instance(v.inter_is_subtype_sst(id, position, recv.mtype.as(MClassType).mclass.vtable.internal_vtable))
else if status == 2 and recv.mtype isa MClassType then
# Perfect hashing
return v.bool_instance(v.inter_is_subtype_ph(id, recv.vtable.mask, recv.mtype.as(MClassType).mclass.vtable.internal_vtable))
else
# Use the slow path (default)
return v.bool_instance(v.is_subtype(recv.mtype, mtype))
end
end
# Optimize a `AIsaExpr`
# `source` the source type of the expression
# `target` the target type of the subtyping test
private fun optimize(v: VirtualMachine, source: MType, target: MType)
do
# If the source class and target class are not classic classes (non-generics) then return
if not source isa MClassType or not target isa MClassType or target isa MGenericType then
return
end
if not target.mclass.abstract_loaded then return
# If the value is positive, the target class has an invariant position in source's structures
var value = source.mclass.get_position_methods(target.mclass)
if value > 0 then
# `value - 2` is the position of the target identifier in source vtable
position = value - 2
status = 1
else
# We use perfect hashing
status = 2
end
id = target.mclass.vtable.id
end
end
redef class AAsCastExpr
# Identifier of the target class type
var id: Int
# If the Cohen test is used, the position of the target id in vtable
var position: Int
# Indicate the status of the optimization for this node
#
# 0 : the default value
# 1 : this test can be implemented with direct access
# 2 : this test must be implemented with perfect hashing
var status: Int = 0
redef fun expr(v)
do
# TODO : a workaround for now
if not v isa VirtualMachine then return super
var recv = v.expr(self.n_expr)
if recv == null then return null
optimize(v, recv.mtype, self.mtype.as(not null))
var mtype = self.mtype.as(not null)
var amtype = v.unanchor_type(mtype)
var res: Bool
if status == 1 and recv.mtype isa MClassType then
# Direct access
res = v.inter_is_subtype_sst(id, position, recv.mtype.as(MClassType).mclass.vtable.internal_vtable)
else if status == 2 and recv.mtype isa MClassType then
# Perfect hashing
res = v.inter_is_subtype_ph(id, recv.vtable.mask, recv.mtype.as(MClassType).mclass.vtable.internal_vtable)
else
# Use the slow path (default)
res = v.is_subtype(recv.mtype, amtype)
end
if not res then
fatal(v, "Cast failed. Expected `{amtype}`, got `{recv.mtype}`")
end
return recv
end
# Optimize a `AAsCastExpr`
# * `source` the source type of the expression
# * `target` the target type of the subtyping test
private fun optimize(v: VirtualMachine, source: MType, target: MType)
do
# If the source class and target class are not classic classes (non-generics) then return
if not source isa MClassType or not target isa MClassType or target isa MGenericType then
return
end
if not target.mclass.loaded then return
# If the value is positive, the target class has an invariant position in source's structures
var value = source.mclass.get_position_methods(target.mclass)
if value > 0 then
# `value - 2` is the position of the target identifier in source vtable
position = value - 2
status = 1
else
# We use perfect hashing
status = 2
end
id = target.mclass.vtable.id
end
end
src/vm/vm_optimizations.nit:17,1--327,3