Example #1
0
 def set_instance_fields(self, value):
     assert isinstance(value, Array)
     self._instance_fields = value
     if (self._layout_for_instances is None
             or value.get_number_of_indexable_fields() !=
             self._layout_for_instances.get_number_of_fields()):
         self._layout_for_instances = ObjectLayout(
             value.get_number_of_indexable_fields(), self)
Example #2
0
 def __init__(self,
              universe,
              number_of_fields=Object.NUMBER_OF_OBJECT_FIELDS,
              obj_class=None):
     _Class.__init__(self, universe, number_of_fields, obj_class)
     if number_of_fields >= 0:
         self._layout_for_instances = ObjectLayout(number_of_fields, self)
     else:
         self._layout_for_instances = None
Example #3
0
 def __init__(self, universe, number_of_fields=-1, obj_class=None):
     Object.__init__(self, obj_class, number_of_fields)
     self._super_class = nilObject
     self._name = None
     self._instance_fields = None
     self._instance_invokables = None
     self._invokables_table = {}
     self._universe = universe
     if number_of_fields >= 0:
         self._layout_for_instances = ObjectLayout(number_of_fields, self)
     else:
         self._layout_for_instances = None
Example #4
0
 def set_instance_fields(self, value):
     assert isinstance(value, Array)
     self._instance_fields = value
     if (self._layout_for_instances is None or
             value.get_number_of_indexable_fields() !=
             self._layout_for_instances.get_number_of_fields()):
         self._layout_for_instances = ObjectLayout(
             value.get_number_of_indexable_fields(), self)
Example #5
0
    def __init__(self, obj_class, number_of_fields=NUMBER_OF_OBJECT_FIELDS):
        cls = obj_class if obj_class is not None else nilObject
        ObjectWithoutFields.__init__(self, cls)

        if obj_class is not None:
            self._object_layout = obj_class.get_layout_for_instances()
        else:
            self._object_layout = ObjectLayout(number_of_fields)

        # IMPORTANT: when changing the number of preallocated fields,
        # you'll also need to update storage_location.py's constants:
        #  NUMBER_OF_PRIMITIVE_FIELDS and NUMBER_OF_POINTER_FIELDS
        self._field1 = nilObject
        self._field2 = nilObject
        self._field3 = nilObject
        self._field4 = nilObject
        self._field5 = nilObject

        self._primField1 = 0
        self._primField2 = 0
        self._primField3 = 0
        self._primField4 = 0
        self._primField5 = 0

        assert (self._object_layout.get_number_of_fields() == number_of_fields)
        # TODO:
        # or obj_class is None
        # or not obj_class._universe.is_object_system_initialized())

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None  ## for some reason _EMPTY_LIST doesn't typecheck here
Example #6
0
 def __init__(self, universe, number_of_fields = -1, obj_class = None):
     Object.__init__(self, obj_class, number_of_fields)
     self._super_class = nilObject
     self._name        = None
     self._instance_fields = None
     self._instance_invokables = None
     self._invokables_table = {}
     self._universe = universe
     if number_of_fields >= 0:
         self._layout_for_instances = ObjectLayout(number_of_fields, self)
     else:
         self._layout_for_instances = None
Example #7
0
class _ClassWithLayout(_Class):
    _immutable_fields_ = ["_layout_for_instances?"]

    def __init__(self,
                 universe,
                 number_of_fields=Object.NUMBER_OF_OBJECT_FIELDS,
                 obj_class=None):
        _Class.__init__(self, universe, number_of_fields, obj_class)
        if number_of_fields >= 0:
            self._layout_for_instances = ObjectLayout(number_of_fields, self)
        else:
            self._layout_for_instances = None

    def set_instance_fields(self, value):
        assert isinstance(value, Array)
        self._instance_fields = value
        if (self._layout_for_instances is None
                or value.get_number_of_indexable_fields() !=
                self._layout_for_instances.get_number_of_fields()):
            self._layout_for_instances = ObjectLayout(
                value.get_number_of_indexable_fields(), self)

    def get_layout_for_instances(self):
        return self._layout_for_instances

    def update_instance_layout_with_initialized_field(self, field_idx,
                                                      spec_type):
        updated = self._layout_for_instances.with_initialized_field(
            field_idx, spec_type)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances

    def update_instance_layout_with_generalized_field(self, field_idx):
        updated = self._layout_for_instances.with_generalized_field(field_idx)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances
Example #8
0
    def __init__(self, obj_class, number_of_fields = NUMBER_OF_OBJECT_FIELDS):
        cls = obj_class if obj_class is not None else nilObject
        ObjectWithoutFields.__init__(self, cls)

        if obj_class is not None:
            self._object_layout = obj_class.get_layout_for_instances()
        else:
            self._object_layout = ObjectLayout(number_of_fields)

        # IMPORTANT: when changing the number of preallocated fields,
        # you'll also need to update storage_location.py's constants:
        #  NUMBER_OF_PRIMITIVE_FIELDS and NUMBER_OF_POINTER_FIELDS
        self._field1 = nilObject
        self._field2 = nilObject
        self._field3 = nilObject
        self._field4 = nilObject
        self._field5 = nilObject

        self._primField1 = 0
        self._primField2 = 0
        self._primField3 = 0
        self._primField4 = 0
        self._primField5 = 0

        assert (self._object_layout.get_number_of_fields() == number_of_fields)
                # TODO:
                # or obj_class is None
                # or not obj_class._universe.is_object_system_initialized())

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None  ## for some reason _EMPTY_LIST doesn't typecheck here
Example #9
0
class Object(ObjectWithoutFields):

    _immutable_fields_ = ["_object_layout?",
                          "_fields?", "_primFields?"]
    
    # Static field indices and number of object fields
    NUMBER_OF_OBJECT_FIELDS = 0

    def __init__(self, obj_class, number_of_fields = NUMBER_OF_OBJECT_FIELDS):
        cls = obj_class if obj_class is not None else nilObject
        ObjectWithoutFields.__init__(self, cls)

        if obj_class is not None:
            self._object_layout = obj_class.get_layout_for_instances()
        else:
            self._object_layout = ObjectLayout(number_of_fields)

        # IMPORTANT: when changing the number of preallocated fields,
        # you'll also need to update storage_location.py's constants:
        #  NUMBER_OF_PRIMITIVE_FIELDS and NUMBER_OF_POINTER_FIELDS
        self._field1 = nilObject
        self._field2 = nilObject
        self._field3 = nilObject
        self._field4 = nilObject
        self._field5 = nilObject

        self._primField1 = 0
        self._primField2 = 0
        self._primField3 = 0
        self._primField4 = 0
        self._primField5 = 0

        assert (self._object_layout.get_number_of_fields() == number_of_fields)
                # TODO:
                # or obj_class is None
                # or not obj_class._universe.is_object_system_initialized())

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None  ## for some reason _EMPTY_LIST doesn't typecheck here

    def get_object_layout(self):
        return promote(self._object_layout)

    def _get_all_fields(self):
        assert not we_are_jitted()
        num_fields = self._object_layout.get_number_of_fields()
        field_values = [None] * num_fields
        for i in range(0, num_fields):
            if self._is_field_set(i):
                field_values[i] = self.get_field(i)
        return field_values

    def _set_all_fields(self, field_values):
        assert not we_are_jitted()
        self._field1 = self._field2 = self._field3 = self._field4 = self._field5 = nilObject
        self._primField1 = self._primField2 = self._primField3 = self._primField4 = self._primField5 = 1234567890

        for i in range(0, self._object_layout.get_number_of_fields()):
            if field_values[i] is None:
                self.set_field(i, nilObject)
            else:
                self.set_field(i, field_values[i])

    def update_layout_to_match_class(self):
        assert not we_are_jitted()
        class_layout = self._class.get_layout_for_instances()
        assert self._object_layout.get_number_of_fields() == class_layout.get_number_of_fields()

        if self._object_layout is not class_layout:
            self._set_layout_and_transfer_fields(class_layout)
            return True
        else:
            return False

    def _set_layout_and_transfer_fields(self, layout):
        assert not we_are_jitted()
        field_values = self._get_all_fields()
        self._object_layout = layout

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None

        self._set_all_fields(field_values)

    def _update_layout_with_initialized_field(self, idx, field_type):
        assert not we_are_jitted()
        layout = self._class.update_instance_layout_with_initialized_field(
            idx, field_type)

        assert layout is not self._object_layout

        self._set_layout_and_transfer_fields(layout)

    def _update_layout_with_generalized_field(self, idx):
        assert not we_are_jitted()
        layout = self._class.update_instance_layout_with_generalized_field(idx)

        assert layout is not self._object_layout
        self._set_layout_and_transfer_fields(layout)

    def get_field_name(self, index):
        # Get the name of the field with the given index
        return self._class.get_instance_field_name(index)

    def get_field_index(self, name):
        # Get the index for the field with the given name
        return self._class.lookup_field_index(name)

    def get_number_of_fields(self):
        # Get the number of fields in this object
        return len(self._fields)

    def is_primitive_set(self, mask):
        return (promote(self._primitive_used_map) & mask) != 0

    def mark_prim_as_set(self, mask):
        if (self._primitive_used_map & mask) == 0:
            self._primitive_used_map |= mask

    def mark_prim_as_unset(self, mask):
        if (self._primitive_used_map & mask) != 0:
            self._primitive_used_map &= ~mask

    def get_location(self, field_idx):
        field_idx = promote(field_idx)
        location = promote(self._object_layout).get_storage_location(field_idx)
        assert location is not None
        return location

    def _is_field_set(self, field_idx):
        return self.get_location(field_idx).is_set(self)

    def get_field(self, field_idx):
        # Get the field with the given index
        assert isinstance(field_idx, int)

        return self.get_location(field_idx).read_location(self)
  
    def set_field(self, field_idx, value):
        # Set the field with the given index to the given value
        assert isinstance(field_idx, int)
        assert isinstance(value, AbstractObject)

        location = self.get_location(field_idx)

        try:
            location.write_location(self, value)
            return
        except UninitializedStorageLocationException:
            self._update_layout_with_initialized_field(field_idx,
                                                       value.__class__)
        except GeneralizeStorageLocationException:
            self._update_layout_with_generalized_field(field_idx)
        self._set_field_after_layout_change(field_idx, value)

    def _set_field_after_layout_change(self, field_idx, value):
        assert not we_are_jitted()

        location = self.get_location(field_idx)
        # we aren't handling potential exceptions here, because,
        # they should not happen by construction
        location.write_location(self, value)
Example #10
0
class ObjectWithLayout(ObjectWithoutFields):

    _immutable_fields_ = ["_object_layout?", "_fields?", "_primFields?"]

    # Static field indices and number of object fields
    NUMBER_OF_OBJECT_FIELDS = 0

    def __init__(self, obj_class, number_of_fields=NUMBER_OF_OBJECT_FIELDS):
        cls = obj_class if obj_class is not None else nilObject
        ObjectWithoutFields.__init__(self, cls)

        if obj_class is not None:
            self._object_layout = obj_class.get_layout_for_instances()
        else:
            self._object_layout = ObjectLayout(number_of_fields)

        # IMPORTANT: when changing the number of preallocated fields,
        # you'll also need to update storage_location.py's constants:
        #  NUMBER_OF_PRIMITIVE_FIELDS and NUMBER_OF_POINTER_FIELDS
        self._field1 = nilObject
        self._field2 = nilObject
        self._field3 = nilObject
        self._field4 = nilObject
        self._field5 = nilObject

        self._primField1 = 0
        self._primField2 = 0
        self._primField3 = 0
        self._primField4 = 0
        self._primField5 = 0

        assert (self._object_layout.get_number_of_fields() == number_of_fields)
        # TODO:
        # or obj_class is None
        # or not obj_class._universe.is_object_system_initialized())

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None  ## for some reason _EMPTY_LIST doesn't typecheck here

    def get_object_layout(self):
        return promote(self._object_layout)

    def _get_all_fields(self):
        assert not we_are_jitted()
        num_fields = self._object_layout.get_number_of_fields()
        field_values = [None] * num_fields
        for i in range(0, num_fields):
            if self._is_field_set(i):
                field_values[i] = self.get_field(i)
        return field_values

    def _set_all_fields(self, field_values):
        assert not we_are_jitted()
        self._field1 = self._field2 = self._field3 = self._field4 = self._field5 = nilObject
        self._primField1 = self._primField2 = self._primField3 = self._primField4 = self._primField5 = 1234567890

        for i in range(0, self._object_layout.get_number_of_fields()):
            if field_values[i] is None:
                self.set_field(i, nilObject)
            else:
                self.set_field(i, field_values[i])

    def update_layout_to_match_class(self):
        assert not we_are_jitted()
        class_layout = self._class.get_layout_for_instances()
        assert self._object_layout.get_number_of_fields(
        ) == class_layout.get_number_of_fields()

        if self._object_layout is not class_layout:
            self._set_layout_and_transfer_fields(class_layout)
            return True
        else:
            return False

    def _set_layout_and_transfer_fields(self, layout):
        assert not we_are_jitted()
        field_values = self._get_all_fields()
        self._object_layout = layout

        n = self._object_layout.get_number_of_used_extended_prim_locations()
        if n > 0:
            self._primFields = [0] * n
        else:
            self._primFields = _EMPTY_LIST

        self._primitive_used_map = 0

        n = self._object_layout.get_number_of_used_extended_ptr_locations()
        if n > 0:
            self._fields = [nilObject] * n
        else:
            self._fields = None

        self._set_all_fields(field_values)

    def _update_layout_with_initialized_field(self, idx, field_type):
        assert not we_are_jitted()
        layout = self._class.update_instance_layout_with_initialized_field(
            idx, field_type)

        assert layout is not self._object_layout

        self._set_layout_and_transfer_fields(layout)

    def _update_layout_with_generalized_field(self, idx):
        assert not we_are_jitted()
        layout = self._class.update_instance_layout_with_generalized_field(idx)

        assert layout is not self._object_layout
        self._set_layout_and_transfer_fields(layout)

    def get_field_name(self, index):
        # Get the name of the field with the given index
        return self._class.get_instance_field_name(index)

    def get_field_index(self, name):
        # Get the index for the field with the given name
        return self._class.lookup_field_index(name)

    def get_number_of_fields(self):
        # Get the number of fields in this object
        return len(self._fields)

    def is_primitive_set(self, mask):
        return (promote(self._primitive_used_map) & mask) != 0

    def mark_prim_as_set(self, mask):
        if (self._primitive_used_map & mask) == 0:
            self._primitive_used_map |= mask

    def mark_prim_as_unset(self, mask):
        if (self._primitive_used_map & mask) != 0:
            self._primitive_used_map &= ~mask

    def get_location(self, field_idx):
        field_idx = promote(field_idx)
        location = promote(self._object_layout).get_storage_location(field_idx)
        assert location is not None
        return location

    def _is_field_set(self, field_idx):
        return self.get_location(field_idx).is_set(self)

    def get_field(self, field_idx):
        # Get the field with the given index
        assert isinstance(field_idx, int)

        return self.get_location(field_idx).read_location(self)

    def set_field(self, field_idx, value):
        # Set the field with the given index to the given value
        assert isinstance(field_idx, int)
        assert isinstance(value, AbstractObject)

        location = self.get_location(field_idx)

        try:
            location.write_location(self, value)
            return
        except UninitializedStorageLocationException:
            self._update_layout_with_initialized_field(field_idx,
                                                       value.__class__)
        except GeneralizeStorageLocationException:
            self._update_layout_with_generalized_field(field_idx)
        self._set_field_after_layout_change(field_idx, value)

    def _set_field_after_layout_change(self, field_idx, value):
        assert not we_are_jitted()

        location = self.get_location(field_idx)
        # we aren't handling potential exceptions here, because,
        # they should not happen by construction
        location.write_location(self, value)
Example #11
0
class Class(Object):
    
    _immutable_fields_ = ["_super_class"
                          "_name",
                          "_instance_fields"
                          "_instance_invokables",
                          "_invokables_table",
                          "_universe",
                          "_layout_for_instances?"]
    
    def __init__(self, universe, number_of_fields = -1, obj_class = None):
        Object.__init__(self, obj_class, number_of_fields)
        self._super_class = nilObject
        self._name        = None
        self._instance_fields = None
        self._instance_invokables = None
        self._invokables_table = {}
        self._universe = universe
        if number_of_fields >= 0:
            self._layout_for_instances = ObjectLayout(number_of_fields, self)
        else:
            self._layout_for_instances = None
        
    def get_super_class(self):
        return self._super_class

    def set_super_class(self, value):
        self._super_class = value
    
    def has_super_class(self):
        return self._super_class is not nilObject

    def get_name(self):
        return self._name
  
    def set_name(self, value):
        self._name = value

    def get_instance_fields(self):
        return self._instance_fields

    def set_instance_fields(self, value):
        assert isinstance(value, Array)
        self._instance_fields = value
        if (self._layout_for_instances is None or
                value.get_number_of_indexable_fields() !=
                self._layout_for_instances.get_number_of_fields()):
            self._layout_for_instances = ObjectLayout(
                value.get_number_of_indexable_fields(), self)
  
    def get_instance_invokables(self):
        return self._instance_invokables
 
    def set_instance_invokables(self, value):
        self._instance_invokables = value
 
        # Make sure this class is the holder of all invokables in the array
        for i in range(0, self.get_number_of_instance_invokables()):
            invokable = self.get_instance_invokable(i)
            assert invokable is not None
            invokable.set_holder(self)
    
    def get_number_of_instance_invokables(self):
        """ Return the number of instance invokables in this class """
        return self.get_instance_invokables().get_number_of_indexable_fields()
  
    def get_instance_invokable(self, index):
        """ Get the instance invokable with the given index """
        return self.get_instance_invokables().get_indexable_field(index)
 
    def set_instance_invokable(self, index, value):
        # Set this class as the holder of the given invokable
        value.set_holder(self)
        self.get_instance_invokables().set_indexable_field(index, value)

    @jit.elidable_promote("all")
    def lookup_invokable(self, signature):
        # Lookup invokable and return if found
        invokable = self._invokables_table.get(signature, None)
        if invokable:
            return invokable
 
        # Lookup invokable with given signature in array of instance invokables
        for i in range(0, self.get_number_of_instance_invokables()):
            invokable = self.get_instance_invokable(i)
            # Return the invokable if the signature matches
            if invokable.get_signature() == signature:
                self._invokables_table[signature] = invokable
                return invokable
      
        # Traverse the super class chain by calling lookup on the super class
        if self.has_super_class():
            invokable = self.get_super_class().lookup_invokable(signature)
            if invokable:
                self._invokables_table[signature] = invokable
                return invokable
 
        # Invokable not found
        return None
 
    def lookup_field_index(self, field_name):
        # Lookup field with given name in array of instance fields
        i = self.get_number_of_instance_fields() - 1
        while i >= 0:
            # Return the current index if the name matches
            if field_name == self.get_instance_field_name(i):
                return i
            i -= 1

        # Field not found
        return -1

    def add_instance_invokable(self, value):
        # Add the given invokable to the array of instance invokables
        for i in range(0, self.get_number_of_instance_invokables()):
            # Get the next invokable in the instance invokable array
            invokable = self.get_instance_invokable(i)
  
            # Replace the invokable with the given one if the signature matches
            if invokable.get_signature() == value.get_signature():
                self.set_instance_invokable(i, value)
                return False
  
        # Append the given method to the array of instance methods
        self.set_instance_invokables(self.get_instance_invokables().copy_and_extend_with(value))
        return True
  
    def add_instance_primitive(self, value, display_warning):
        if self.add_instance_invokable(value) and display_warning:
            from som.vm.universe import std_print, std_println
            std_print("Warning: Primitive " + value.get_signature().get_string())
            std_println(" is not in class definition for class " + self.get_name().get_string())
  
    def get_instance_field_name(self, index):
        return self.get_instance_fields().get_indexable_field(index)
 
    def get_number_of_instance_fields(self):
        # Get the total number of instance fields in this class
        return self.get_instance_fields().get_number_of_indexable_fields()

    @staticmethod
    def _includes_primitives(clazz):
        for i in range(0, clazz.get_number_of_instance_invokables()):
            # Get the next invokable in the instance invokable array
            if clazz.get_instance_invokable(i).is_primitive():
                return True
        return False

    def has_primitives(self):
        return (self._includes_primitives(self) or
                self._includes_primitives(self._class))

    def load_primitives(self, display_warning):
        from som.primitives.known import (primitives_for_class,
                                          PrimitivesNotFound)
        try:
            prim_class = primitives_for_class(self)
            prim_class(self._universe, display_warning).install_primitives_in(self)
        except PrimitivesNotFound:
            if display_warning:
                from som.vm.universe import error_println
                error_println("Loading of primitives failed for %s. Currently, "
                              "we support primitives only for known classes" % self.get_name())

    def __str__(self):
        return "Class(" + self.get_name().get_string() + ")"

    def get_layout_for_instances(self):
        return self._layout_for_instances

    def update_instance_layout_with_initialized_field(self, field_idx,
                                                      spec_type):
        updated = self._layout_for_instances.with_initialized_field(field_idx,
                                                                    spec_type)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances

    def update_instance_layout_with_generalized_field(self, field_idx):
        updated = self._layout_for_instances.with_generalized_field(field_idx)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances
Example #12
0
class Class(Object):

    _immutable_fields_ = [
        "_super_class"
        "_name", "_instance_fields"
        "_instance_invokables", "_invokables_table", "_universe",
        "_layout_for_instances?"
    ]

    def __init__(self, universe, number_of_fields=-1, obj_class=None):
        Object.__init__(self, obj_class, number_of_fields)
        self._super_class = nilObject
        self._name = None
        self._instance_fields = None
        self._instance_invokables = None
        self._invokables_table = {}
        self._universe = universe
        if number_of_fields >= 0:
            self._layout_for_instances = ObjectLayout(number_of_fields, self)
        else:
            self._layout_for_instances = None

    def get_super_class(self):
        return self._super_class

    def set_super_class(self, value):
        self._super_class = value

    def has_super_class(self):
        return self._super_class is not nilObject

    def get_name(self):
        return self._name

    def set_name(self, value):
        self._name = value

    def get_instance_fields(self):
        return self._instance_fields

    def set_instance_fields(self, value):
        assert isinstance(value, Array)
        self._instance_fields = value
        if (self._layout_for_instances is None
                or value.get_number_of_indexable_fields() !=
                self._layout_for_instances.get_number_of_fields()):
            self._layout_for_instances = ObjectLayout(
                value.get_number_of_indexable_fields(), self)

    def get_instance_invokables(self):
        return self._instance_invokables

    def set_instance_invokables(self, value):
        self._instance_invokables = value

        # Make sure this class is the holder of all invokables in the array
        for i in range(0, self.get_number_of_instance_invokables()):
            invokable = self.get_instance_invokable(i)
            assert invokable is not None
            invokable.set_holder(self)

    def get_number_of_instance_invokables(self):
        """ Return the number of instance invokables in this class """
        return self.get_instance_invokables().get_number_of_indexable_fields()

    def get_instance_invokable(self, index):
        """ Get the instance invokable with the given index """
        return self.get_instance_invokables().get_indexable_field(index)

    def set_instance_invokable(self, index, value):
        # Set this class as the holder of the given invokable
        value.set_holder(self)
        self.get_instance_invokables().set_indexable_field(index, value)

    @jit.elidable_promote("all")
    def lookup_invokable(self, signature):
        # Lookup invokable and return if found
        invokable = self._invokables_table.get(signature, None)
        if invokable:
            return invokable

        # Lookup invokable with given signature in array of instance invokables
        for i in range(0, self.get_number_of_instance_invokables()):
            invokable = self.get_instance_invokable(i)
            # Return the invokable if the signature matches
            if invokable.get_signature() == signature:
                self._invokables_table[signature] = invokable
                return invokable

        # Traverse the super class chain by calling lookup on the super class
        if self.has_super_class():
            invokable = self.get_super_class().lookup_invokable(signature)
            if invokable:
                self._invokables_table[signature] = invokable
                return invokable

        # Invokable not found
        return None

    def lookup_field_index(self, field_name):
        # Lookup field with given name in array of instance fields
        i = self.get_number_of_instance_fields() - 1
        while i >= 0:
            # Return the current index if the name matches
            if field_name == self.get_instance_field_name(i):
                return i
            i -= 1

        # Field not found
        return -1

    def add_instance_invokable(self, value):
        # Add the given invokable to the array of instance invokables
        for i in range(0, self.get_number_of_instance_invokables()):
            # Get the next invokable in the instance invokable array
            invokable = self.get_instance_invokable(i)

            # Replace the invokable with the given one if the signature matches
            if invokable.get_signature() == value.get_signature():
                self.set_instance_invokable(i, value)
                return False

        # Append the given method to the array of instance methods
        self.set_instance_invokables(
            self.get_instance_invokables().copy_and_extend_with(value))
        return True

    def add_instance_primitive(self, value, display_warning):
        if self.add_instance_invokable(value) and display_warning:
            from som.vm.universe import std_print, std_println
            std_print("Warning: Primitive " +
                      value.get_signature().get_string())
            std_println(" is not in class definition for class " +
                        self.get_name().get_string())

    def get_instance_field_name(self, index):
        return self.get_instance_fields().get_indexable_field(index)

    def get_number_of_instance_fields(self):
        # Get the total number of instance fields in this class
        return self.get_instance_fields().get_number_of_indexable_fields()

    @staticmethod
    def _includes_primitives(clazz):
        for i in range(0, clazz.get_number_of_instance_invokables()):
            # Get the next invokable in the instance invokable array
            if clazz.get_instance_invokable(i).is_primitive():
                return True
        return False

    def has_primitives(self):
        return (self._includes_primitives(self)
                or self._includes_primitives(self._class))

    def load_primitives(self, display_warning):
        from som.primitives.known import (primitives_for_class,
                                          PrimitivesNotFound)
        try:
            prim_class = primitives_for_class(self)
            prim_class(self._universe,
                       display_warning).install_primitives_in(self)
        except PrimitivesNotFound:
            if display_warning:
                from som.vm.universe import error_println
                error_println(
                    "Loading of primitives failed for %s. Currently, "
                    "we support primitives only for known classes" %
                    self.get_name())

    def __str__(self):
        return "Class(" + self.get_name().get_string() + ")"

    def get_layout_for_instances(self):
        return self._layout_for_instances

    def update_instance_layout_with_initialized_field(self, field_idx,
                                                      spec_type):
        updated = self._layout_for_instances.with_initialized_field(
            field_idx, spec_type)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances

    def update_instance_layout_with_generalized_field(self, field_idx):
        updated = self._layout_for_instances.with_generalized_field(field_idx)
        if updated is not self._layout_for_instances:
            self._layout_for_instances = updated
        return self._layout_for_instances