A virtual machine based on the naive_interpreter

Introduced properties

private var _current_propdef: APropdef

nitc :: VirtualMachine :: _current_propdef

The currently analyzed APropdef
private var _initialization_value: Instance

nitc :: VirtualMachine :: _initialization_value

The unique instance of the MInit value
private var _memory_manager: MemoryManager

nitc :: VirtualMachine :: _memory_manager

Handles memory allocated in C
private var _ph: Perfecthashing

nitc :: VirtualMachine :: _ph

Perfect hashing and perfect numbering
fun current_propdef: APropdef

nitc :: VirtualMachine :: current_propdef

The currently analyzed APropdef
protected fun current_propdef=(current_propdef: APropdef)

nitc :: VirtualMachine :: current_propdef=

The currently analyzed APropdef
init defaultinit(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])

nitc :: VirtualMachine :: defaultinit

private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer

nitc :: VirtualMachine :: init_internal_attributes

Initialize the internal representation of an object (its attribute values)
fun initialization_value: Instance

nitc :: VirtualMachine :: initialization_value

The unique instance of the MInit value
protected fun initialization_value=(initialization_value: Instance)

nitc :: VirtualMachine :: initialization_value=

The unique instance of the MInit value
fun inter_is_subtype_ph(id: Int, mask: Int, vtable: Pointer): Bool

nitc :: VirtualMachine :: inter_is_subtype_ph

Subtyping test with perfect hashing
fun inter_is_subtype_sst(id: Int, position: Int, vtable: Pointer): Bool

nitc :: VirtualMachine :: inter_is_subtype_sst

Subtyping test with Cohen test (direct access)
fun load_class(mclass: MClass)

nitc :: VirtualMachine :: load_class

Load the class and create its runtime structures, this loading is explicit
fun load_class_indirect(mclass: MClass)

nitc :: VirtualMachine :: load_class_indirect

This method is called to handle an implicitly loaded class,
private fun load_supers(mclass: MClass)

nitc :: VirtualMachine :: load_supers

Recursively load superclasses.
fun memory_manager: MemoryManager

nitc :: VirtualMachine :: memory_manager

Handles memory allocated in C
protected fun memory_manager=(memory_manager: MemoryManager)

nitc :: VirtualMachine :: memory_manager=

Handles memory allocated in C
private fun method_dispatch(mproperty: MMethod, vtable: VTable, recv: Instance): MMethodDef

nitc :: VirtualMachine :: method_dispatch

Method dispatch, for a given global method mproperty
fun method_dispatch_ph(vtable: Pointer, mask: Int, id: Int, offset: Int): MMethodDef

nitc :: VirtualMachine :: method_dispatch_ph

Execute a method dispatch with perfect hashing and return the appropriate MMethodDef
fun method_dispatch_sst(vtable: Pointer, absolute_offset: Int): MMethodDef

nitc :: VirtualMachine :: method_dispatch_sst

Execute a method dispatch with direct access and return the appropriate MMethodDef
fun numbering(n: nullable AExpr, position: Int): Int

nitc :: VirtualMachine :: numbering

Number the variables in n.
fun ph: Perfecthashing

nitc :: VirtualMachine :: ph

Perfect hashing and perfect numbering
protected fun ph=(ph: Perfecthashing)

nitc :: VirtualMachine :: ph=

Perfect hashing and perfect numbering
fun read_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int): Instance

nitc :: VirtualMachine :: read_attribute_ph

Return the attribute value in instance with a sequence of perfect_hashing
fun read_attribute_sst(instance: Pointer, offset: Int): Instance

nitc :: VirtualMachine :: read_attribute_sst

Return the attribute value in instance with a direct access (SST)
fun send_optimize(callsite: CallSite, args: Array[Instance]): nullable Instance

nitc :: VirtualMachine :: send_optimize

Try to have the most efficient implementation of the method dispatch
fun write_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int, value: Instance)

nitc :: VirtualMachine :: write_attribute_ph

Replace the value of an attribute in an instance
fun write_attribute_sst(instance: Pointer, offset: Int, value: Instance)

nitc :: VirtualMachine :: write_attribute_sst

Replace the value of an attribute in an instance with direct access

Redefined properties

redef type FRAME: VmFrame

nitc :: variables_numbering $ VirtualMachine :: FRAME

The frames of the VirtualMachine are specialized
redef type SELF: VirtualMachine

nitc $ VirtualMachine :: SELF

Type of this instance, automatically specialized in every class
redef fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance

nitc :: vm_optimizations $ VirtualMachine :: callsite

Add optimization of the method dispatch
redef init init

nitc $ VirtualMachine :: init

redef fun init_instance(recv: Instance)

nitc $ VirtualMachine :: init_instance

Redef init_instance to simulate the loading of a class
redef fun init_instance_primitive(recv: Instance)

nitc $ VirtualMachine :: init_instance_primitive

Associate a PrimitiveInstance to its VTable
redef fun is_subtype(sub: MType, sup: MType): Bool

nitc $ VirtualMachine :: is_subtype

Runtime subtyping test
redef fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool

nitc $ VirtualMachine :: isset_attribute

Is the attribute mproperty initialized in the instance recv?
redef fun new_frame(node: ANode, mpropdef: MPropDef, args: Array[Instance]): FRAME

nitc :: variables_numbering $ VirtualMachine :: new_frame

Redef to add the numbering of variables and arguments
redef fun new_frame(node: ANode, mpropdef: MPropDef, args: Array[Instance]): FRAME

nitc :: compilation $ VirtualMachine :: new_frame

Initialize the environment for a call and return a new Frame
redef fun read_attribute(mproperty: MAttribute, recv: Instance): Instance

nitc $ VirtualMachine :: read_attribute

Return the value of the attribute mproperty for the object recv
redef fun read_variable(v: Variable): Instance

nitc :: variables_numbering $ VirtualMachine :: read_variable

Read a Variable from a frame by using its position
redef fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance

nitc $ VirtualMachine :: send

Execute mproperty for a args (where args[0] is the receiver).
redef fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)

nitc $ VirtualMachine :: write_attribute

Replace in recv the value of the attribute mproperty by value
redef fun write_variable(v: Variable, value: Instance)

nitc :: variables_numbering $ VirtualMachine :: write_variable

Assign the value of the Variable in an environment

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type FRAME: Frame

nitc :: NaiveInterpreter :: FRAME

The virtual type of the frames used in the execution engine
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
private var _arguments: Array[String]

nitc :: NaiveInterpreter :: _arguments

The command line arguments of the interpreted program
private var _c_compiler: String

nitc :: NaiveInterpreter :: _c_compiler

External compiler used to generate the foreign code library
private var _catch_count: Int

nitc :: NaiveInterpreter :: _catch_count

The count of catch blocs that have been encountered and can catch an abort
private var _compile_dir: String

nitc :: NaiveInterpreter :: _compile_dir

Where to store generated C and extracted code
private var _current_propdef: APropdef

nitc :: VirtualMachine :: _current_propdef

The currently analyzed APropdef
private var _discover_call_trace: Set[MMethodDef]

nitc :: NaiveInterpreter :: _discover_call_trace

Store known methods, used to trace methods as they are reached
private var _error_instance: MutableInstance

nitc :: NaiveInterpreter :: _error_instance

Placebo instance used to mark internal error result when null already have a meaning.
private var _escapemark: nullable EscapeMark

nitc :: NaiveInterpreter :: _escapemark

Is a return, a break or a continue executed?
private var _escapevalue: nullable Instance

nitc :: NaiveInterpreter :: _escapevalue

The value associated with the current return/break/continue, if any.
private var _false_instance: Instance

nitc :: NaiveInterpreter :: _false_instance

The unique instance of the false value.
private var _frames: List[FRAME]

nitc :: NaiveInterpreter :: _frames

The stack of all frames. The first one is the current one.
private var _initialization_value: Instance

nitc :: VirtualMachine :: _initialization_value

The unique instance of the MInit value
private var _last_error: nullable FatalError

nitc :: NaiveInterpreter :: _last_error

The last error thrown on abort/runtime error where catch_count > 0
private var _mainmodule: MModule

nitc :: NaiveInterpreter :: _mainmodule

The main module of the program (used to lookup method)
private var _mainobj: nullable Instance

nitc :: NaiveInterpreter :: _mainobj

The main Sys instance
private var _memory_manager: MemoryManager

nitc :: VirtualMachine :: _memory_manager

Handles memory allocated in C
private var _modelbuilder: ModelBuilder

nitc :: NaiveInterpreter :: _modelbuilder

The modelbuilder that know the AST and its associations with the model
private var _null_instance: Instance

nitc :: NaiveInterpreter :: _null_instance

The unique instance of the null value.
private var _onces: Map[ANode, Instance]

nitc :: NaiveInterpreter :: _onces

Map used to store values of nodes that must be evaluated once in the system (AOnceExpr)
private var _ph: Perfecthashing

nitc :: VirtualMachine :: _ph

Perfect hashing and perfect numbering
private var _routine_types: Set[String]

nitc :: NaiveInterpreter :: _routine_types

Name of all supported functional names
private var _true_instance: Instance

nitc :: NaiveInterpreter :: _true_instance

The unique instance of the true value.
fun aexprs_to_instances(aexprs: Iterator[AExpr]): nullable Array[Instance]

nitc :: NaiveInterpreter :: aexprs_to_instances

Consumes an iterator of expressions and tries to map each element to
fun arguments: Array[String]

nitc :: NaiveInterpreter :: arguments

The command line arguments of the interpreted program
protected fun arguments=(arguments: Array[String])

nitc :: NaiveInterpreter :: arguments=

The command line arguments of the interpreted program
fun array_instance(values: Array[Instance], elttype: MType): Instance

nitc :: NaiveInterpreter :: array_instance

Return a new array made of values.
fun bool_instance(val: Bool): Instance

nitc :: NaiveInterpreter :: bool_instance

Return the boolean instance associated with val.
fun byte_instance(val: Byte): Instance

nitc :: NaiveInterpreter :: byte_instance

Return the byte instance associated with val.
private fun c_compiler: String

nitc :: NaiveInterpreter :: c_compiler

External compiler used to generate the foreign code library
private fun c_compiler=(c_compiler: String)

nitc :: NaiveInterpreter :: c_compiler=

External compiler used to generate the foreign code library
fun c_string_instance(txt: String): Instance

nitc :: NaiveInterpreter :: c_string_instance

Return a new C string initialized with txt
fun c_string_instance_fast_cstr(txt: CString, from: Int): Instance

nitc :: NaiveInterpreter :: c_string_instance_fast_cstr

Return a new C string instance sharing the same data space as txt
fun c_string_instance_from_ns(txt: CString, len: Int): Instance

nitc :: NaiveInterpreter :: c_string_instance_from_ns

Return a new C string initialized with txt
fun c_string_instance_len(length: Int): PrimitiveInstance[CString]

nitc :: NaiveInterpreter :: c_string_instance_len

Return a new C string initialized of length
fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance

nitc :: NaiveInterpreter :: call

Execute mpropdef for a args (where args[0] is the receiver).
fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance

nitc :: NaiveInterpreter :: callsite

Execute a full callsite for given args
fun catch_count: Int

nitc :: NaiveInterpreter :: catch_count

The count of catch blocs that have been encountered and can catch an abort
fun catch_count=(catch_count: Int)

nitc :: NaiveInterpreter :: catch_count=

The count of catch blocs that have been encountered and can catch an abort
fun char_instance(val: Char): Instance

nitc :: NaiveInterpreter :: char_instance

Return the char instance associated with val.
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]

nitc :: NaiveInterpreter :: collect_attr_propdef

Collect attributes of a type in the order of their init
private fun compile_dir: String

nitc :: NaiveInterpreter :: compile_dir

Where to store generated C and extracted code
private fun compile_dir=(compile_dir: String)

nitc :: NaiveInterpreter :: compile_dir=

Where to store generated C and extracted code
fun current_node: nullable ANode

nitc :: NaiveInterpreter :: current_node

The current node, used to print errors, debug and stack-traces
fun current_propdef: APropdef

nitc :: VirtualMachine :: current_propdef

The currently analyzed APropdef
protected fun current_propdef=(current_propdef: APropdef)

nitc :: VirtualMachine :: current_propdef=

The currently analyzed APropdef
fun current_receiver_class: MClassType

nitc :: NaiveInterpreter :: current_receiver_class

The dynamic type of the current self
fun debug(message: String)

nitc :: NaiveInterpreter :: debug

Debug on the current node
init defaultinit(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])

nitc :: VirtualMachine :: defaultinit

init defaultinit(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])

nitc :: NaiveInterpreter :: defaultinit

fun discover_call_trace: Set[MMethodDef]

nitc :: NaiveInterpreter :: discover_call_trace

Store known methods, used to trace methods as they are reached
protected fun discover_call_trace=(discover_call_trace: Set[MMethodDef])

nitc :: NaiveInterpreter :: discover_call_trace=

Store known methods, used to trace methods as they are reached
fun error_instance: MutableInstance

nitc :: NaiveInterpreter :: error_instance

Placebo instance used to mark internal error result when null already have a meaning.
protected fun error_instance=(error_instance: MutableInstance)

nitc :: NaiveInterpreter :: error_instance=

Placebo instance used to mark internal error result when null already have a meaning.
fun escapemark: nullable EscapeMark

nitc :: NaiveInterpreter :: escapemark

Is a return, a break or a continue executed?
protected fun escapemark=(escapemark: nullable EscapeMark)

nitc :: NaiveInterpreter :: escapemark=

Is a return, a break or a continue executed?
fun escapevalue: nullable Instance

nitc :: NaiveInterpreter :: escapevalue

The value associated with the current return/break/continue, if any.
protected fun escapevalue=(escapevalue: nullable Instance)

nitc :: NaiveInterpreter :: escapevalue=

The value associated with the current return/break/continue, if any.
fun expr(n: AExpr): nullable Instance

nitc :: NaiveInterpreter :: expr

Evaluate n as an expression in the current context.
fun false_instance: Instance

nitc :: NaiveInterpreter :: false_instance

The unique instance of the false value.
protected fun false_instance=(false_instance: Instance)

nitc :: NaiveInterpreter :: false_instance=

The unique instance of the false value.
fun fatal(message: String)

nitc :: NaiveInterpreter :: fatal

Exit the program with a message
fun float_instance(val: Float): Instance

nitc :: NaiveInterpreter :: float_instance

Return the float instance associated with val.
fun force_get_primitive_method(name: String, recv: MType): MMethod

nitc :: NaiveInterpreter :: force_get_primitive_method

Get a primitive method in the context of the main module
fun foreign_code_lib_path(mmodule: MModule): String

nitc :: NaiveInterpreter :: foreign_code_lib_path

Path of the compiled foreign code library
fun frame: FRAME

nitc :: NaiveInterpreter :: frame

The current frame used to store local variables of the current method executed
fun frames: List[FRAME]

nitc :: NaiveInterpreter :: frames

The stack of all frames. The first one is the current one.
protected fun frames=(frames: List[FRAME])

nitc :: NaiveInterpreter :: frames=

The stack of all frames. The first one is the current one.
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun hash: Int

core :: Object :: hash

The hash code of the object.
init init

core :: Object :: init

fun init_instance(recv: Instance)

nitc :: NaiveInterpreter :: init_instance

Fill the initial values of the newly created instance recv.
fun init_instance_primitive(recv: Instance)

nitc :: NaiveInterpreter :: init_instance_primitive

A hook to initialize a PrimitiveInstance
private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer

nitc :: VirtualMachine :: init_internal_attributes

Initialize the internal representation of an object (its attribute values)
fun initialization_value: Instance

nitc :: VirtualMachine :: initialization_value

The unique instance of the MInit value
protected fun initialization_value=(initialization_value: Instance)

nitc :: VirtualMachine :: initialization_value=

The unique instance of the MInit value
fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
fun int16_instance(val: Int16): Instance

nitc :: NaiveInterpreter :: int16_instance

Return the int16 instance associated with val.
fun int32_instance(val: Int32): Instance

nitc :: NaiveInterpreter :: int32_instance

Return the int32 instance associated with val.
fun int8_instance(val: Int8): Instance

nitc :: NaiveInterpreter :: int8_instance

Return the int8 instance associated with val.
fun int_instance(val: Int): Instance

nitc :: NaiveInterpreter :: int_instance

Return the integer instance associated with val.
fun inter_is_subtype_ph(id: Int, mask: Int, vtable: Pointer): Bool

nitc :: VirtualMachine :: inter_is_subtype_ph

Subtyping test with perfect hashing
fun inter_is_subtype_sst(id: Int, position: Int, vtable: Pointer): Bool

nitc :: VirtualMachine :: inter_is_subtype_sst

Subtyping test with Cohen test (direct access)
fun is_escape(escapemark: nullable EscapeMark): Bool

nitc :: NaiveInterpreter :: is_escape

If there is a break/continue and is associated with escapemark, then return true and clear the mark.
fun is_escaping: Bool

nitc :: NaiveInterpreter :: is_escaping

Is a return or a break or a continue executed?
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
fun is_subtype(sub: MType, sup: MType): Bool

nitc :: NaiveInterpreter :: is_subtype

Subtype test in the context of the mainmodule
fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool

nitc :: NaiveInterpreter :: isset_attribute

Is the attribute mproperty initialized the instance recv?
fun last_error: nullable FatalError

nitc :: NaiveInterpreter :: last_error

The last error thrown on abort/runtime error where catch_count > 0
protected fun last_error=(last_error: nullable FatalError)

nitc :: NaiveInterpreter :: last_error=

The last error thrown on abort/runtime error where catch_count > 0
fun load_class(mclass: MClass)

nitc :: VirtualMachine :: load_class

Load the class and create its runtime structures, this loading is explicit
fun load_class_indirect(mclass: MClass)

nitc :: VirtualMachine :: load_class_indirect

This method is called to handle an implicitly loaded class,
private fun load_supers(mclass: MClass)

nitc :: VirtualMachine :: load_supers

Recursively load superclasses.
fun mainmodule: MModule

nitc :: NaiveInterpreter :: mainmodule

The main module of the program (used to lookup method)
fun mainmodule=(mainmodule: MModule)

nitc :: NaiveInterpreter :: mainmodule=

The main module of the program (used to lookup method)
fun mainobj: nullable Instance

nitc :: NaiveInterpreter :: mainobj

The main Sys instance
protected fun mainobj=(mainobj: nullable Instance)

nitc :: NaiveInterpreter :: mainobj=

The main Sys instance
fun memory_manager: MemoryManager

nitc :: VirtualMachine :: memory_manager

Handles memory allocated in C
protected fun memory_manager=(memory_manager: MemoryManager)

nitc :: VirtualMachine :: memory_manager=

Handles memory allocated in C
private fun method_dispatch(mproperty: MMethod, vtable: VTable, recv: Instance): MMethodDef

nitc :: VirtualMachine :: method_dispatch

Method dispatch, for a given global method mproperty
fun method_dispatch_ph(vtable: Pointer, mask: Int, id: Int, offset: Int): MMethodDef

nitc :: VirtualMachine :: method_dispatch_ph

Execute a method dispatch with perfect hashing and return the appropriate MMethodDef
fun method_dispatch_sst(vtable: Pointer, absolute_offset: Int): MMethodDef

nitc :: VirtualMachine :: method_dispatch_sst

Execute a method dispatch with direct access and return the appropriate MMethodDef
fun modelbuilder: ModelBuilder

nitc :: NaiveInterpreter :: modelbuilder

The modelbuilder that know the AST and its associations with the model
protected fun modelbuilder=(modelbuilder: ModelBuilder)

nitc :: NaiveInterpreter :: modelbuilder=

The modelbuilder that know the AST and its associations with the model
private intern fun native_class_name: CString

core :: Object :: native_class_name

The class name of the object in CString format.
fun new_frame(node: ANode, mpropdef: MPropDef, args: Array[Instance]): FRAME

nitc :: NaiveInterpreter :: new_frame

Initialize the environment for a call and return a new Frame
fun null_instance: Instance

nitc :: NaiveInterpreter :: null_instance

The unique instance of the null value.
protected fun null_instance=(null_instance: Instance)

nitc :: NaiveInterpreter :: null_instance=

The unique instance of the null value.
fun numbering(n: nullable AExpr, position: Int): Int

nitc :: VirtualMachine :: numbering

Number the variables in n.
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun onces: Map[ANode, Instance]

nitc :: NaiveInterpreter :: onces

Map used to store values of nodes that must be evaluated once in the system (AOnceExpr)
protected fun onces=(onces: Map[ANode, Instance])

nitc :: NaiveInterpreter :: onces=

Map used to store values of nodes that must be evaluated once in the system (AOnceExpr)
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
fun parameter_check(node: ANode, mpropdef: MMethodDef, args: Array[Instance])

nitc :: NaiveInterpreter :: parameter_check

Execute type checks of covariant parameters
fun ph: Perfecthashing

nitc :: VirtualMachine :: ph

Perfect hashing and perfect numbering
protected fun ph=(ph: Perfecthashing)

nitc :: VirtualMachine :: ph=

Perfect hashing and perfect numbering
private fun process_id: Int

nitc :: NaiveInterpreter :: process_id

Identifier for this process, unique between running interpreters
fun read_attribute(mproperty: MAttribute, recv: Instance): Instance

nitc :: NaiveInterpreter :: read_attribute

Read the attribute mproperty of an instance recv and return its value.
fun read_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int): Instance

nitc :: VirtualMachine :: read_attribute_ph

Return the attribute value in instance with a sequence of perfect_hashing
fun read_attribute_sst(instance: Pointer, offset: Int): Instance

nitc :: VirtualMachine :: read_attribute_sst

Return the attribute value in instance with a direct access (SST)
fun read_variable(v: Variable): Instance

nitc :: NaiveInterpreter :: read_variable

Retrieve the value of the variable in the current frame
fun routine_types: Set[String]

nitc :: NaiveInterpreter :: routine_types

Name of all supported functional names
protected fun routine_types=(routine_types: Set[String])

nitc :: NaiveInterpreter :: routine_types=

Name of all supported functional names
fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance

nitc :: NaiveInterpreter :: send

Execute mproperty for a args (where args[0] is the receiver).
fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance

nitc :: NaiveInterpreter :: send_commons

Common code for runtime injected calls and normal calls
fun send_optimize(callsite: CallSite, args: Array[Instance]): nullable Instance

nitc :: VirtualMachine :: send_optimize

Try to have the most efficient implementation of the method dispatch
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
fun stack_trace: String

nitc :: NaiveInterpreter :: stack_trace

Return a stack trace. One line per function
fun start(mainmodule: MModule)

nitc :: NaiveInterpreter :: start

Starts the interpreter on the main module of a program
fun stmt(n: nullable AExpr)

nitc :: NaiveInterpreter :: stmt

Evaluate n as a statement in the current context.
fun string_instance(txt: String): Instance

nitc :: NaiveInterpreter :: string_instance

Return a new String instance for txt
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_s: String

core :: Object :: to_s

User readable representation of self.
fun true_instance: Instance

nitc :: NaiveInterpreter :: true_instance

The unique instance of the true value.
protected fun true_instance=(true_instance: Instance)

nitc :: NaiveInterpreter :: true_instance=

The unique instance of the true value.
fun uint16_instance(val: UInt16): Instance

nitc :: NaiveInterpreter :: uint16_instance

Return the uint16 instance associated with val.
fun uint32_instance(val: UInt32): Instance

nitc :: NaiveInterpreter :: uint32_instance

Return the uint32 instance associated with val.
fun unanchor_type(mtype: MType): MType

nitc :: NaiveInterpreter :: unanchor_type

This function determines the correct type according to the receiver of the current propdef (self).
fun value_instance(object: Object): Instance

nitc :: NaiveInterpreter :: value_instance

Return a instance associated to a primitive class
fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]

nitc :: NaiveInterpreter :: varargize

Evaluate args as expressions in the call of mpropdef on recv.
fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)

nitc :: NaiveInterpreter :: write_attribute

Replace in recv the value of the attribute mproperty by value
fun write_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int, value: Instance)

nitc :: VirtualMachine :: write_attribute_ph

Replace the value of an attribute in an instance
fun write_attribute_sst(instance: Pointer, offset: Int, value: Instance)

nitc :: VirtualMachine :: write_attribute_sst

Replace the value of an attribute in an instance with direct access
fun write_variable(v: Variable, value: Instance)

nitc :: NaiveInterpreter :: write_variable

Assign the value of the variable in the current frame
package_diagram nitc::VirtualMachine VirtualMachine nitc::NaiveInterpreter NaiveInterpreter nitc::VirtualMachine->nitc::NaiveInterpreter core::Object Object nitc::NaiveInterpreter->core::Object ...core::Object ... ...core::Object->core::Object

Ancestors

interface Object

core :: Object

The root of the class hierarchy.

Parents

class NaiveInterpreter

nitc :: NaiveInterpreter

The visitor that interprets the Nit Program by walking on the AST

Class definitions

nitc $ VirtualMachine
# 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

nitc :: variables_numbering $ VirtualMachine
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

nitc :: vm_optimizations $ VirtualMachine
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

nitc :: compilation $ VirtualMachine
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