nitc :: VirtualMachine :: _current_propdef
The currently analyzed APropdefnitc :: VirtualMachine :: _initialization_value
The unique instance of theMInit
value
nitc :: VirtualMachine :: _memory_manager
Handles memory allocated in Cnitc :: VirtualMachine :: current_propdef
The currently analyzed APropdefnitc :: VirtualMachine :: current_propdef=
The currently analyzed APropdefnitc :: VirtualMachine :: defaultinit
nitc :: VirtualMachine :: init_internal_attributes
Initialize the internal representation of an object (its attribute values)nitc :: VirtualMachine :: initialization_value
The unique instance of theMInit
value
nitc :: VirtualMachine :: initialization_value=
The unique instance of theMInit
value
nitc :: VirtualMachine :: inter_is_subtype_ph
Subtyping test with perfect hashingnitc :: VirtualMachine :: inter_is_subtype_sst
Subtyping test with Cohen test (direct access)nitc :: VirtualMachine :: load_class
Load the class and create its runtime structures, this loading is explicitnitc :: VirtualMachine :: load_class_indirect
This method is called to handle an implicitly loaded class,nitc :: VirtualMachine :: load_supers
Recursively load superclasses.nitc :: VirtualMachine :: memory_manager
Handles memory allocated in Cnitc :: VirtualMachine :: memory_manager=
Handles memory allocated in Cnitc :: VirtualMachine :: method_dispatch
Method dispatch, for a given global methodmproperty
nitc :: VirtualMachine :: method_dispatch_ph
Execute a method dispatch with perfect hashing and return the appropriateMMethodDef
nitc :: VirtualMachine :: method_dispatch_sst
Execute a method dispatch with direct access and return the appropriateMMethodDef
nitc :: VirtualMachine :: ph=
Perfect hashing and perfect numberingnitc :: VirtualMachine :: read_attribute_ph
Return the attribute value ininstance
with a sequence of perfect_hashing
nitc :: VirtualMachine :: read_attribute_sst
Return the attribute value ininstance
with a direct access (SST)
nitc :: VirtualMachine :: send_optimize
Try to have the most efficient implementation of the method dispatchnitc :: VirtualMachine :: write_attribute_ph
Replace the value of an attribute in an instancenitc :: VirtualMachine :: write_attribute_sst
Replace the value of an attribute in an instance with direct accessnitc :: variables_numbering $ VirtualMachine :: FRAME
The frames of the VirtualMachine are specializednitc $ VirtualMachine :: SELF
Type of this instance, automatically specialized in every classnitc :: vm_optimizations $ VirtualMachine :: callsite
Add optimization of the method dispatchnitc $ VirtualMachine :: init
nitc $ VirtualMachine :: init_instance
Redef init_instance to simulate the loading of a classnitc $ VirtualMachine :: init_instance_primitive
Associate aPrimitiveInstance
to its VTable
nitc $ VirtualMachine :: is_subtype
Runtime subtyping testnitc $ VirtualMachine :: isset_attribute
Is the attributemproperty
initialized in the instance recv
?
nitc :: variables_numbering $ VirtualMachine :: new_frame
Redef to add the numbering of variables and argumentsnitc :: compilation $ VirtualMachine :: new_frame
Initialize the environment for a call and return a new Framenitc $ VirtualMachine :: read_attribute
Return the value of the attributemproperty
for the object recv
nitc :: variables_numbering $ VirtualMachine :: read_variable
Read aVariable
from a frame by using its position
nitc $ VirtualMachine :: write_attribute
Replace inrecv
the value of the attribute mproperty
by value
nitc :: variables_numbering $ VirtualMachine :: write_variable
Assign the value of theVariable
in an environment
nitc :: NaiveInterpreter :: FRAME
The virtual type of the frames used in the execution enginenitc :: NaiveInterpreter :: _arguments
The command line arguments of the interpreted programnitc :: NaiveInterpreter :: _c_compiler
External compiler used to generate the foreign code librarynitc :: NaiveInterpreter :: _catch_count
The count ofcatch
blocs that have been encountered and can catch an abort
nitc :: NaiveInterpreter :: _compile_dir
Where to store generated C and extracted codenitc :: VirtualMachine :: _current_propdef
The currently analyzed APropdefnitc :: NaiveInterpreter :: _discover_call_trace
Store known methods, used to trace methods as they are reachednitc :: NaiveInterpreter :: _error_instance
Placebo instance used to mark internal error result whennull
already have a meaning.
nitc :: NaiveInterpreter :: _escapemark
Is a return, a break or a continue executed?nitc :: NaiveInterpreter :: _escapevalue
The value associated with the current return/break/continue, if any.nitc :: NaiveInterpreter :: _false_instance
The unique instance of thefalse
value.
nitc :: VirtualMachine :: _initialization_value
The unique instance of theMInit
value
nitc :: NaiveInterpreter :: _last_error
The last error thrown on abort/runtime error where catch_count > 0nitc :: NaiveInterpreter :: _mainmodule
The main module of the program (used to lookup method)nitc :: VirtualMachine :: _memory_manager
Handles memory allocated in Cnitc :: NaiveInterpreter :: _modelbuilder
The modelbuilder that know the AST and its associations with the modelnitc :: NaiveInterpreter :: _null_instance
The unique instance of thenull
value.
nitc :: NaiveInterpreter :: _routine_types
Name of all supported functional namesnitc :: NaiveInterpreter :: _true_instance
The unique instance of thetrue
value.
nitc :: NaiveInterpreter :: aexprs_to_instances
Consumes an iterator of expressions and tries to map each element tonitc :: NaiveInterpreter :: arguments=
The command line arguments of the interpreted programnitc :: NaiveInterpreter :: array_instance
Return a new array made ofvalues
.
nitc :: NaiveInterpreter :: bool_instance
Return the boolean instance associated withval
.
nitc :: NaiveInterpreter :: byte_instance
Return the byte instance associated withval
.
nitc :: NaiveInterpreter :: c_compiler
External compiler used to generate the foreign code librarynitc :: NaiveInterpreter :: c_compiler=
External compiler used to generate the foreign code librarynitc :: NaiveInterpreter :: c_string_instance
Return a new C string initialized withtxt
nitc :: NaiveInterpreter :: c_string_instance_fast_cstr
Return a new C string instance sharing the same data space astxt
nitc :: NaiveInterpreter :: c_string_instance_from_ns
Return a new C string initialized withtxt
nitc :: NaiveInterpreter :: c_string_instance_len
Return a new C string initialized oflength
nitc :: NaiveInterpreter :: call
Executempropdef
for a args
(where args[0]
is the receiver).
nitc :: NaiveInterpreter :: catch_count
The count ofcatch
blocs that have been encountered and can catch an abort
nitc :: NaiveInterpreter :: catch_count=
The count ofcatch
blocs that have been encountered and can catch an abort
nitc :: NaiveInterpreter :: char_instance
Return the char instance associated withval
.
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
nitc :: NaiveInterpreter :: collect_attr_propdef
Collect attributes of a type in the order of their initnitc :: NaiveInterpreter :: compile_dir
Where to store generated C and extracted codenitc :: NaiveInterpreter :: compile_dir=
Where to store generated C and extracted codenitc :: NaiveInterpreter :: current_node
The current node, used to print errors, debug and stack-tracesnitc :: VirtualMachine :: current_propdef
The currently analyzed APropdefnitc :: VirtualMachine :: current_propdef=
The currently analyzed APropdefnitc :: NaiveInterpreter :: current_receiver_class
The dynamic type of the currentself
nitc :: VirtualMachine :: defaultinit
nitc :: NaiveInterpreter :: defaultinit
core :: Object :: defaultinit
nitc :: NaiveInterpreter :: discover_call_trace
Store known methods, used to trace methods as they are reachednitc :: NaiveInterpreter :: discover_call_trace=
Store known methods, used to trace methods as they are reachednitc :: NaiveInterpreter :: error_instance
Placebo instance used to mark internal error result whennull
already have a meaning.
nitc :: NaiveInterpreter :: error_instance=
Placebo instance used to mark internal error result whennull
already have a meaning.
nitc :: NaiveInterpreter :: escapemark
Is a return, a break or a continue executed?nitc :: NaiveInterpreter :: escapemark=
Is a return, a break or a continue executed?nitc :: NaiveInterpreter :: escapevalue
The value associated with the current return/break/continue, if any.nitc :: NaiveInterpreter :: escapevalue=
The value associated with the current return/break/continue, if any.nitc :: NaiveInterpreter :: false_instance
The unique instance of thefalse
value.
nitc :: NaiveInterpreter :: false_instance=
The unique instance of thefalse
value.
nitc :: NaiveInterpreter :: float_instance
Return the float instance associated withval
.
nitc :: NaiveInterpreter :: force_get_primitive_method
Get a primitive method in the context of the main modulenitc :: NaiveInterpreter :: foreign_code_lib_path
Path of the compiled foreign code librarynitc :: NaiveInterpreter :: frame
The current frame used to store local variables of the current method executednitc :: NaiveInterpreter :: init_instance
Fill the initial values of the newly created instancerecv
.
nitc :: NaiveInterpreter :: init_instance_primitive
A hook to initialize aPrimitiveInstance
nitc :: VirtualMachine :: init_internal_attributes
Initialize the internal representation of an object (its attribute values)nitc :: VirtualMachine :: initialization_value
The unique instance of theMInit
value
nitc :: VirtualMachine :: initialization_value=
The unique instance of theMInit
value
nitc :: NaiveInterpreter :: int16_instance
Return the int16 instance associated withval
.
nitc :: NaiveInterpreter :: int32_instance
Return the int32 instance associated withval
.
nitc :: NaiveInterpreter :: int8_instance
Return the int8 instance associated withval
.
nitc :: NaiveInterpreter :: int_instance
Return the integer instance associated withval
.
nitc :: VirtualMachine :: inter_is_subtype_ph
Subtyping test with perfect hashingnitc :: VirtualMachine :: inter_is_subtype_sst
Subtyping test with Cohen test (direct access)nitc :: NaiveInterpreter :: is_escape
If there is a break/continue and is associated withescapemark
, then return true and clear the mark.
nitc :: NaiveInterpreter :: is_escaping
Is a return or a break or a continue executed?core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
nitc :: NaiveInterpreter :: is_subtype
Subtype test in the context of the mainmodulenitc :: NaiveInterpreter :: isset_attribute
Is the attributemproperty
initialized the instance recv
?
nitc :: NaiveInterpreter :: last_error
The last error thrown on abort/runtime error where catch_count > 0nitc :: NaiveInterpreter :: last_error=
The last error thrown on abort/runtime error where catch_count > 0nitc :: VirtualMachine :: load_class
Load the class and create its runtime structures, this loading is explicitnitc :: VirtualMachine :: load_class_indirect
This method is called to handle an implicitly loaded class,nitc :: VirtualMachine :: load_supers
Recursively load superclasses.nitc :: NaiveInterpreter :: mainmodule
The main module of the program (used to lookup method)nitc :: NaiveInterpreter :: mainmodule=
The main module of the program (used to lookup method)nitc :: NaiveInterpreter :: mainobj=
The main Sys instancenitc :: VirtualMachine :: memory_manager
Handles memory allocated in Cnitc :: VirtualMachine :: memory_manager=
Handles memory allocated in Cnitc :: VirtualMachine :: method_dispatch
Method dispatch, for a given global methodmproperty
nitc :: VirtualMachine :: method_dispatch_ph
Execute a method dispatch with perfect hashing and return the appropriateMMethodDef
nitc :: VirtualMachine :: method_dispatch_sst
Execute a method dispatch with direct access and return the appropriateMMethodDef
nitc :: NaiveInterpreter :: modelbuilder
The modelbuilder that know the AST and its associations with the modelnitc :: NaiveInterpreter :: modelbuilder=
The modelbuilder that know the AST and its associations with the modelcore :: Object :: native_class_name
The class name of the object in CString format.nitc :: NaiveInterpreter :: null_instance
The unique instance of thenull
value.
nitc :: NaiveInterpreter :: null_instance=
The unique instance of thenull
value.
core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: NaiveInterpreter :: parameter_check
Execute type checks of covariant parametersnitc :: VirtualMachine :: ph=
Perfect hashing and perfect numberingnitc :: NaiveInterpreter :: process_id
Identifier for this process, unique between running interpretersnitc :: NaiveInterpreter :: read_attribute
Read the attributemproperty
of an instance recv
and return its value.
nitc :: VirtualMachine :: read_attribute_ph
Return the attribute value ininstance
with a sequence of perfect_hashing
nitc :: VirtualMachine :: read_attribute_sst
Return the attribute value ininstance
with a direct access (SST)
nitc :: NaiveInterpreter :: read_variable
Retrieve the value of the variable in the current framenitc :: NaiveInterpreter :: routine_types
Name of all supported functional namesnitc :: NaiveInterpreter :: routine_types=
Name of all supported functional namesnitc :: NaiveInterpreter :: send_commons
Common code for runtime injected calls and normal callsnitc :: VirtualMachine :: send_optimize
Try to have the most efficient implementation of the method dispatchnitc :: NaiveInterpreter :: stack_trace
Return a stack trace. One line per functionnitc :: NaiveInterpreter :: start
Starts the interpreter on the main module of a programnitc :: NaiveInterpreter :: stmt
Evaluaten
as a statement in the current context.
nitc :: NaiveInterpreter :: string_instance
Return a new String instance fortxt
nitc :: NaiveInterpreter :: true_instance
The unique instance of thetrue
value.
nitc :: NaiveInterpreter :: true_instance=
The unique instance of thetrue
value.
nitc :: NaiveInterpreter :: uint16_instance
Return the uint16 instance associated withval
.
nitc :: NaiveInterpreter :: uint32_instance
Return the uint32 instance associated withval
.
nitc :: NaiveInterpreter :: unanchor_type
This function determines the correct type according to the receiver of the current propdef (self).nitc :: NaiveInterpreter :: value_instance
Return a instance associated to a primitive classnitc :: NaiveInterpreter :: varargize
Evaluateargs
as expressions in the call of mpropdef
on recv
.
nitc :: NaiveInterpreter :: write_attribute
Replace inrecv
the value of the attribute mproperty
by value
nitc :: VirtualMachine :: write_attribute_ph
Replace the value of an attribute in an instancenitc :: VirtualMachine :: write_attribute_sst
Replace the value of an attribute in an instance with direct accessnitc :: NaiveInterpreter :: write_variable
Assign the value of the variable in the current frame
# A virtual machine based on the naive_interpreter
class VirtualMachine super NaiveInterpreter
# Perfect hashing and perfect numbering
var ph: Perfecthashing = new Perfecthashing
# Handles memory allocated in C
var memory_manager: MemoryManager = new MemoryManager
# The unique instance of the `MInit` value
var initialization_value: Instance is noinit
init
do
var init_type = new MInitType(mainmodule.model)
initialization_value = new MutableInstance(init_type)
super
end
# Runtime subtyping test
redef fun is_subtype(sub, sup: MType): Bool
do
if sub == sup then return true
var anchor = self.frame.arguments.first.mtype.as(MClassType)
# `sub` or `sup` are formal or virtual types, resolve them to concrete types
if sub isa MFormalType then
sub = sub.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
if sup isa MFormalType then
sup = sup.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
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
if sub isa MFormalType 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
# and `sup` can be discovered inside a Generic type during the subtyping test
if not sub.mclass.loaded then load_class(sub.mclass)
# If the target of the test is not-loaded yet, the subtyping-test will be false
if not sup.mclass.abstract_loaded then return false
# For now, always use perfect hashing for subtyping test
var super_id = sup.mclass.vtable.id
var mask = sub.mclass.vtable.mask
var res = inter_is_subtype_ph(super_id, mask, sub.mclass.vtable.internal_vtable)
if not res then return false
# sub and sup can be generic types, each argument of generics has to be tested
if not sup isa MGenericType then return true
var sub2 = sub.supertype_to(mainmodule, anchor, sup.mclass)
# Test each argument of a generic by recursive calls
for i in [0..sup.mclass.arity[ do
var sub_arg = sub2.arguments[i]
var sup_arg = sup.arguments[i]
var res2 = is_subtype(sub_arg, sup_arg)
if not res2 then return false
end
return true
end
# Subtyping test with perfect hashing
# * `id` is the identifier of the target class
# * `mask` is the perfect hashing mask of the receiver class
# * `vtable` is the pointer to the virtual table of the receiver class
fun inter_is_subtype_ph(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;
`}
# Subtyping test with Cohen test (direct access)
# * `id` is the identifier of the target class
# * `mask` is the absolute position of the target identifier in the virtual table
# * `vtable` is the pointer to the virtual table of the receiver class
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
if not recv.mtype.as(MClassType).mclass.loaded then load_class(recv.mtype.as(MClassType).mclass)
recv.vtable = recv.mtype.as(MClassType).mclass.vtable
assert recv isa MutableInstance
recv.internal_attributes = init_internal_attributes(initialization_value, recv.mtype.as(MClassType).mclass.mattributes.length)
super
end
# Associate a `PrimitiveInstance` to its `VTable`
redef fun init_instance_primitive(recv: Instance)
do
if not recv.mtype.as(MClassType).mclass.loaded then load_class(recv.mtype.as(MClassType).mclass)
recv.vtable = recv.mtype.as(MClassType).mclass.vtable
end
# Initialize the internal representation of an object (its attribute values)
# `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<size; i++)
attributes[i] = init_instance;
Instance_incr_ref(init_instance);
return attributes;
`}
# Load the class and create its runtime structures, this loading is explicit
fun load_class(mclass: MClass)
do
if mclass.loaded then return
load_supers(mclass)
if mclass.abstract_loaded then
mclass.allocate_vtable(self)
else
mclass.make_vt(self, true)
end
end
# Recursively load superclasses.
private fun load_supers(mclass: MClass)
do
for parent in mclass.in_hierarchy(mainmodule).direct_greaters do
load_class_indirect(parent)
end
end
# This method is called to handle an implicitly loaded class,
# i.e. a superclass of an explicitly loaded class
# A class loaded implicitly will not be fully allocated
fun load_class_indirect(mclass: MClass)
do
# It the class was already implicitly loaded
if mclass.abstract_loaded then return
load_supers(mclass)
mclass.make_vt(self, false)
end
# Execute `mproperty` for a `args` (where `args[0]` is the receiver).
redef fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
do
var recv = args.first
var mtype = recv.mtype
var ret = send_commons(mproperty, args, mtype)
if ret != null then return ret
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, recv: Instance): MMethodDef
do
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)
end
end
# Execute a method dispatch with perfect hashing and return the appropriate `MMethodDef`
# * `vtable` Pointer to the internal virtual table of the class
# * `mask` Perfect hashing mask of the receiver class
# * `id` Identifier of the class which introduce the method
# * `offset` Relative offset of the method from the beginning of the block
fun method_dispatch_ph(vtable: Pointer, mask: Int, id: Int, offset: Int): MMethodDef `{
// Perfect hashing position
int hv = mask & id;
long unsigned int *pointer = (long unsigned int*)(((long int *)vtable)[-hv]);
// pointer+2 is the position where methods are
// Add the offset of property and get the method implementation
MMethodDef propdef = (MMethodDef)*(pointer + 2 + offset);
return propdef;
`}
# Execute a method dispatch with direct access and return the appropriate `MMethodDef`
# * `vtable` Pointer to the internal virtual table of the class
# * `absolute_offset` Absolute offset from the beginning of the virtual table
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
assert recv isa MutableInstance
var i: Instance
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, position + mproperty.offset)
else
# Otherwise, read the attribute value with perfect hashing
var id = mproperty.intro_mclassdef.mclass.vtable.id
i = read_attribute_ph(recv.internal_attributes, recv.vtable.internal_vtable,
recv.vtable.mask, id, mproperty.offset)
end
# If we get a `MInit` value, throw an error
if i == initialization_value then
fatal("Uninitialized attribute {mproperty.name}")
abort
end
return i
end
# Return the attribute value in `instance` with a sequence of perfect_hashing
# * `instance` is the attributes array of the receiver
# * `vtable` is the pointer to the virtual table of the class (of the receiver)
# * `mask` is the perfect hashing mask of the class
# * `id` is the identifier of the class
# * `offset` is the relative offset of this attribute
fun read_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int): Instance `{
// Perfect hashing position
int hv = mask & id;
long unsigned int *pointer = (long unsigned int*)(((long int *)vtable)[-hv]);
// pointer+1 is the position where the delta of the class is
int absolute_offset = *(pointer + 1);
Instance res = ((Instance *)instance)[absolute_offset + offset];
return res;
`}
# Return the attribute value in `instance` with a direct access (SST)
# * `instance` is the attributes array of the receiver
# * `offset` is the absolute offset of this attribute
fun read_attribute_sst(instance: Pointer, offset: Int): Instance `{
/* We can make a direct access to the attribute value
because this attribute is always at the same position
for the class of this receiver */
Instance res = ((Instance *)instance)[offset];
return res;
`}
# Replace in `recv` the value of the attribute `mproperty` by `value`
redef fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
do
assert recv isa MutableInstance
# Replace the old value of mproperty in recv
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, position + mproperty.offset, value)
else
# Otherwise, use perfect hashing to replace the old value
var id = mproperty.intro_mclassdef.mclass.vtable.id
write_attribute_ph(recv.internal_attributes, recv.vtable.internal_vtable,
recv.vtable.mask, id, mproperty.offset, value)
end
end
# Replace the value of an attribute in an instance
# * `instance` is the attributes array of the receiver
# * `vtable` is the pointer to the virtual table of the class (of the receiver)
# * `mask` is the perfect hashing mask of the class
# * `id` is the identifier of the class
# * `offset` is the relative offset of this attribute
# * `value` is the new value for this attribute
fun write_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int, value: Instance) `{
// Perfect hashing position
int hv = mask & id;
long unsigned int *pointer = (long unsigned int*)(((long int *)vtable)[-hv]);
// pointer+1 is the position where the delta of the class is
int absolute_offset = *(pointer + 1);
((Instance *)instance)[absolute_offset + offset] = value;
Instance_incr_ref(value);
`}
# Replace the value of an attribute in an instance with direct access
# * `instance` is the attributes array of the receiver
# * `offset` is the absolute offset of this attribute
# * `value` is the new value for this attribute
fun write_attribute_sst(instance: Pointer, offset: Int, value: Instance) `{
// Direct access to the position with the absolute offset
((Instance *)instance)[offset] = value;
Instance_incr_ref(value);
`}
# Is the attribute `mproperty` initialized in the instance `recv`?
redef fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
do
assert recv isa MutableInstance
# Read the attribute value with internal perfect hashing read
# because we do not want to throw an error if the value is `initialization_value`
var id = mproperty.intro_mclassdef.mclass.vtable.id
var i = read_attribute_ph(recv.internal_attributes, recv.vtable.internal_vtable,
recv.vtable.mask, id, mproperty.offset)
return i != initialization_value
end
end
src/vm/virtual_machine.nit:37,1--406,3
redef class VirtualMachine
# The frames of the VirtualMachine are specialized
redef type FRAME: VmFrame
# Number the variables in `n`.
# Do nothing if `n` is null
fun numbering(n: nullable AExpr, position: Int): Int
do
if n == null then return position
var pos = n.numbering(self, position)
return pos
end
# Redef to add the numbering of variables and arguments
redef fun new_frame(node, mpropdef, args)
do
var f = new VmFrame(node, mpropdef, args)
# If this Frame is for a method or an attribute block then number variables into the body of the method
if node isa APropdef then
# Compile the code (number its local variables)
if not node.is_compiled then node.compile(self)
# Create an empty environment
f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size)
end
# Putting self at the beginning of the environment
f.variables[0] = args[0]
return f
end
# Read a `Variable` from a frame by using its position
redef fun read_variable(v: Variable): Instance
do
return frame.variables[v.position]
end
# Assign the value of the `Variable` in an environment
redef fun write_variable(v: Variable, value: Instance)
do
frame.variables[v.position] = value
end
end
src/vm/variables_numbering.nit:22,1--67,3
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
src/vm/vm_optimizations.nit:22,1--52,3
redef class VirtualMachine
# The currently analyzed APropdef
var current_propdef: APropdef
redef fun new_frame(node, mpropdef, args)
do
# Save the current propdef
if node isa APropdef then self.current_propdef = node
return super
end
end
src/vm/compilation.nit:23,1--35,3