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 __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 __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 __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 __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
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
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
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)
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)
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
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