WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 91c4af20 authored by Stefan Marr's avatar Stefan Marr
Browse files

Changing to new object model of core-lib



Introduction of AbstractObject without fields and classes.
Methods are not Arrays anymore to simplify and avoid use of 'object fields'.
Frames are not entirely implementation specific.

- clean out superficial comments
- added missing primitives
Signed-off-by: default avatarStefan Marr <git@stefan-marr.de>
parent 9bd2c541
Subproject commit 555c692765b3853feb7fa3cdcd260440d9ec1422
Subproject commit b2d362a1f4ffdb6a2a6ad036eb8d582073ddad45
......@@ -67,7 +67,7 @@ class ClassGenerationContext(object):
result_class.set_instance_invokables(self._universe.new_array_from_list(self._class_methods))
result_class.set_name(self._universe.symbol_for(ccname))
super_mclass = super_class.get_class()
super_mclass = super_class.get_class(self._universe)
result_class.set_super_class(super_mclass)
# Allocate the resulting class
......@@ -86,6 +86,6 @@ class ClassGenerationContext(object):
system_class.set_instance_fields(self._universe.new_array_from_list(self._instance_fields))
# class-bound == class-instance-bound
super_mclass = system_class.get_class()
super_mclass = system_class.get_class(self._universe.nilObject)
super_mclass.set_instance_invokables(self._universe.new_array_from_list(self._class_methods))
super_mclass.set_instance_fields(self._universe.new_array_from_list(self._class_fields))
from som.vm.universe import error_print, error_println
from som.vm.universe import error_print, error_println, get_current
from som.interpreter.bytecodes import bytecode_as_str, bytecode_length, Bytecodes
def dump(clazz):
......@@ -61,7 +61,7 @@ def dump_method(m, indent):
constant = m.get_constant(b)
error_println("(index: " + str(m.get_bytecode(b + 1)) +
") value: (" +
str(constant.get_class().get_name()) +
str(constant.get_class(get_current()).get_name()) +
") " + str(constant))
elif bytecode == Bytecodes.push_global:
error_println("(index: " + str(m.get_bytecode(b + 1)) +
......
......@@ -29,22 +29,14 @@ class MethodGenerationContext(object):
return empty_primitive(self._signature.get_string(), universe)
def assemble(self, universe):
# create a method instance with the given number of bytecodes and literals
num_literals = len(self._literals)
num_locals = len(self._locals)
meth = universe.new_method(self._signature,
len(self._bytecode),
num_literals,
self._literals,
universe.new_integer(num_locals),
universe.new_integer(self._compute_stack_depth()))
# copy literals into the method
i = 0
for l in self._literals:
meth.set_indexable_field(i, l)
i += 1
# copy bytecodes into method
i = 0
for bc in self._bytecode:
......
......@@ -89,7 +89,7 @@ class Parser(object):
if super_name.get_string() != "nil":
super_class = self._universe.load_class(super_name)
cgenc.set_instance_fields_of_super(super_class.get_instance_fields())
cgenc.set_class_fields_of_super(super_class.get_class().get_instance_fields())
cgenc.set_class_fields_of_super(super_class.get_class(self._universe).get_instance_fields())
else:
# WARNING:
# We hardcode here the field names for Class
......
from rpython.rlib import jit
from som.vmobjects.array import Array
# Frame layout:
#
......@@ -12,128 +11,105 @@ from som.vmobjects.array import Array
# | ... |
# +-----------------+
#
class Frame(Array):
class Frame(object):
# Static field indices and number of frame fields
NUMBER_OF_FRAME_FIELDS = Array.NUMBER_OF_OBJECT_FIELDS
_immutable_fields_ = ["_method", "_context"]
_immutable_fields_ = ["_method", "_context", "_stack"]
def __init__(self, nilObject, num_elements, method, context, previous_frame):
Array.__init__(self, nilObject, num_elements)
self._stack_pointer = 0
self._bytecode_index = 0
self._method = method
self._context = context
self._previous_frame = previous_frame if previous_frame else nilObject
self._stack = [nilObject] * num_elements
self._stack_pointer = 0
self._bytecode_index = 0
self._previous_frame = previous_frame
def get_previous_frame(self):
# Get the previous frame by reading the field with previous frame index
return self._previous_frame
def clear_previous_frame(self, nilObject):
# Set the previous frame to nil
self._previous_frame = nilObject
def clear_previous_frame(self):
self._previous_frame = None
def has_previous_frame(self, nilObject):
return self._previous_frame != nilObject
def has_previous_frame(self):
return self._previous_frame is not None
def is_bootstrap_frame(self, nilObject):
return not self.has_previous_frame(nilObject)
def is_bootstrap_frame(self):
return not self.has_previous_frame()
def get_context(self):
# Get the context by reading the field with context index
return self._context
def has_context(self, nilObject):
return self._context != nilObject
def has_context(self):
return self._context is not None
@jit.unroll_safe
def _get_context(self, level):
# Get the context frame at the given level
""" Get the context frame at the given level """
frame = self
# Iterate through the context chain until the given level is reached
for _ in range(level, 0, -1):
# Get the context of the current frame
frame = frame.get_context()
# Return the found context
return frame
@jit.unroll_safe
def get_outer_context(self, nilObject):
# Compute the outer context of this frame
def get_outer_context(self):
""" Compute the outer context of this frame """
frame = self
# Iterate through the context chain until null is reached
while frame.has_context(nilObject):
while frame.has_context():
frame = frame.get_context()
# Return the outer context
return frame
def get_method(self):
# Get the method by reading the field with method index
return self._method
def get_number_of_arguments(self):
return self.get_method().get_number_of_arguments()
def _get_default_number_of_fields(self):
# Return the default number of fields in a frame
return self.NUMBER_OF_FRAME_FIELDS
return self._method.get_number_of_arguments()
def pop(self):
# Pop an object from the expression stack and return it
stack_pointer = self.get_stack_pointer()
self.set_stack_pointer(stack_pointer - 1)
return self.get_indexable_field(stack_pointer)
""" Pop an object from the expression stack and return it """
stack_pointer = self._stack_pointer
self._stack_pointer = stack_pointer - 1
return self._stack[stack_pointer]
def push(self, value):
# Push an object onto the expression stack
stack_pointer = self.get_stack_pointer() + 1
self.set_indexable_field(stack_pointer, value)
self.set_stack_pointer(stack_pointer)
def get_stack_pointer(self):
# Get the current stack pointer for this frame
return jit.promote(self._stack_pointer)
def set_stack_pointer(self, value):
# Set the current stack pointer for this frame
self._stack_pointer = value
""" Push an object onto the expression stack """
stack_pointer = self._stack_pointer + 1
self._stack[stack_pointer] = value
self._stack_pointer = stack_pointer
def reset_stack_pointer(self):
""" Set the stack pointer to its initial value thereby clearing
the stack """
# arguments are stored in front of local variables
# Set the stack pointer to its initial value thereby clearing the stack
self.set_stack_pointer(self.get_number_of_arguments() +
self._stack_pointer = (self.get_number_of_arguments() +
self.get_method().get_number_of_locals().get_embedded_integer() - 1)
def get_bytecode_index(self):
# Get the current bytecode index for this frame
return self._bytecode_index
def set_bytecode_index(self, value):
# Set the current bytecode index for this frame
self._bytecode_index = value
def get_stack_element(self, index):
# Get the stack element with the given index
# (an index of zero yields the top element)
return self.get_indexable_field(self.get_stack_pointer() - index)
return self._stack[self._stack_pointer - index]
def set_stack_element(self, index, value):
# Set the stack element with the given index to the given value
# (an index of zero yields the top element)
self.set_indexable_field(self.get_stack_pointer() - index, value)
self._stack[self._stack_pointer - index] = value
def _get_local(self, index):
return self.get_indexable_field(self.get_number_of_arguments() + index)
return self._stack[self.get_number_of_arguments() + index]
def _set_local(self, index, value):
self.set_indexable_field(self.get_number_of_arguments() + index, value)
self._stack[self.get_number_of_arguments() + index] = value
def get_local(self, index, context_level):
# Get the local with the given index in the given context
......@@ -149,14 +125,14 @@ class Frame(Array):
context = self._get_context(context_level)
# Get the argument with the given index
return context.get_indexable_field(index)
return context._stack[index]
def set_argument(self, index, context_level, value):
# Get the context
context = self._get_context(context_level)
# Set the argument with the given index to the given value
context.set_indexable_field(index, value)
context._stack[index] = value
@jit.unroll_safe
def copy_arguments_from(self, frame):
......@@ -165,7 +141,7 @@ class Frame(Array):
# - copy them into the argument area of the current frame
num_args = self.get_method().get_number_of_arguments()
for i in range(0, num_args):
self.set_indexable_field(i, frame.get_stack_element(num_args - 1 - i))
self._stack[i] = frame.get_stack_element(num_args - 1 - i)
def print_stack_trace(self, nilObject):
# Print a stack trace starting in this frame
......@@ -174,5 +150,5 @@ class Frame(Array):
std_println(" %d @ %s" % (self.get_bytecode_index(),
self.get_method().get_signature().get_string()))
if self.has_previous_frame(nilObject):
self.get_previous_frame().print_stack_trace(nilObject)
if self.has_previous_frame():
self.get_previous_frame().print_stack_trace()
from som.interpreter.bytecodes import bytecode_length, Bytecodes
from som.vmobjects.clazz import Class
from rpython.rlib import jit
......@@ -122,16 +123,16 @@ class Interpreter(object):
result = frame.pop()
# Compute the context for the non-local return
context = frame.get_outer_context(self._universe.nilObject)
context = frame.get_outer_context()
# Make sure the block context is still on the stack
if not context.has_previous_frame(self._universe.nilObject):
if not context.has_previous_frame():
# Try to recover by sending 'escapedBlock:' to the sending object
# this can get a bit nasty when using nested blocks. In this case
# the "sender" will be the surrounding block and not the object
# that actually sent the 'value' message.
block = frame.get_argument(0, 0)
sender = frame.get_previous_frame().get_outer_context(self._universe.nilObject).get_argument(0, 0)
sender = frame.get_previous_frame().get_outer_context().get_argument(0, 0)
# pop the frame of the currently executing block...
self._pop_frame()
......@@ -141,7 +142,7 @@ class Interpreter(object):
return
# Unwind the frames
while self.get_frame() != context:
while self.get_frame() is not context:
self._pop_frame()
# Pop the top frame and push the result
......@@ -158,7 +159,7 @@ class Interpreter(object):
receiver = frame.get_stack_element(num_args - 1)
# Send the message
self._send(signature, receiver.get_class(), bytecode_index)
self._send(signature, receiver.get_class(self._universe), bytecode_index)
def start(self):
......@@ -241,7 +242,7 @@ class Interpreter(object):
def get_self(self):
# Get the self object from the interpreter
return self.get_frame().get_outer_context(self._universe.nilObject).get_argument(0, 0)
return self.get_frame().get_outer_context().get_argument(0, 0)
def _send(self, selector, receiver_class, bytecode_index):
# First try the inline cache
......@@ -283,7 +284,7 @@ class Interpreter(object):
self.set_frame(self._frame.get_previous_frame())
# Destroy the previous pointer on the old top frame
result.clear_previous_frame(self._universe.nilObject)
result.clear_previous_frame()
# Return the popped frame
return result
......
......@@ -6,6 +6,26 @@ def _new(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(interpreter.get_universe().new_instance(rcvr))
def _name(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_name())
def _super_class(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_super_class())
def _methods(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_instance_invokables())
def _fields(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_instance_fields())
class ClassPrimitives(Primitives):
def install_primitives(self):
self._install_instance_primitive(Primitive("new", self._universe, _new))
self._install_instance_primitive(Primitive("name", self._universe, _name))
self._install_instance_primitive(Primitive("superclass", self._universe, _super_class))
self._install_instance_primitive(Primitive("methods", self._universe, _methods))
self._install_instance_primitive(Primitive("fields", self._universe, _fields))
from som.primitives.primitives import Primitives
from som.vmobjects.primitive import Primitive
def _holder(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_holder())
def _signature(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_signature())
class MethodPrimitives(Primitives):
def install_primitives(self):
self._install_instance_primitive(Primitive("holder", self._universe, _holder))
self._install_instance_primitive(Primitive("signature", self._universe, _signature))
......@@ -2,6 +2,7 @@ from rpython.rlib.objectmodel import compute_identity_hash
from som.primitives.primitives import Primitives
from som.vmobjects.object import Object
from som.vmobjects.primitive import Primitive
from som.vmobjects.array import Array
......@@ -20,9 +21,12 @@ def _hashcode(ivkbl, frame, interpreter):
def _objectSize(ivkbl, frame, interpreter):
rcvr = frame.pop()
size = 0
if isinstance(rcvr, Object):
size = rcvr.get_number_of_fields()
if isinstance(rcvr, Array):
size += rcvr.get_number_of_indexable_fields()
elif isinstance(rcvr, Array):
size = rcvr.get_number_of_indexable_fields()
frame.push(interpreter.get_universe().new_integer(size))
......@@ -30,7 +34,7 @@ def _perform(ivkbl, frame, interpreter):
selector = frame.pop()
rcvr = frame.get_stack_element(0)
invokable = rcvr.get_class().lookup_invokable(selector)
invokable = rcvr.get_class(interpreter.get_universe()).lookup_invokable(selector)
invokable.invoke(frame, interpreter)
def _performInSuperclass(ivkbl, frame, interpreter):
......@@ -49,7 +53,7 @@ def _performWithArguments(ivkbl, frame, interpreter):
for i in range(0, args.get_number_of_indexable_fields()):
frame.push(args.get_indexable_field(i))
invokable = rcvr.get_class().lookup_invokable(selector)
invokable = rcvr.get_class(interpreter.get_universe()).lookup_invokable(selector)
invokable.invoke(frame, interpreter)
def _instVarAt(ivkbl, frame, interpreter):
......@@ -71,7 +75,7 @@ def _halt(ivkbl, frame, interpreter):
def _class(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_class())
frame.push(rcvr.get_class(interpreter.get_universe()))
......
from som.primitives.primitives import Primitives
from som.vmobjects.primitive import Primitive
def _holder(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_holder())
def _signature(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(rcvr.get_signature())
class PrimitivePrimitives(Primitives):
def install_primitives(self):
self._install_instance_primitive(Primitive("holder", self._universe, _holder))
self._install_instance_primitive(Primitive("signature", self._universe, _signature))
......@@ -21,4 +21,4 @@ class Primitives(object):
def _install_class_primitive(self, primitive):
# Install the given primitive as an instance primitive in the class of
# the holder class
self._holder.get_class().add_instance_primitive(primitive)
self._holder.get_class(self._universe).add_instance_primitive(primitive)
......@@ -20,11 +20,12 @@ def _length(ivkbl, frame, interpreter):
def _equals(ivkbl, frame, interpreter):
op1 = frame.pop()
op2 = frame.pop() # rcvr
if op1.get_class() == interpreter.get_universe().stringClass:
universe = interpreter.get_universe()
if op1.get_class(universe) == universe.stringClass:
if op1.get_embedded_string() == op2.get_embedded_string():
frame.push(interpreter.get_universe().trueObject)
frame.push(universe.trueObject)
return
frame.push(interpreter.get_universe().falseObject)
frame.push(universe.falseObject)
def _substring(ivkbl, frame, interpreter):
end = frame.pop()
......
......@@ -20,7 +20,7 @@ class Shell(object):
std_println("SOM Shell. Type \"quit\" to exit.\n");
# Create a fake bootstrap frame
current_frame = self._interpreter.push_new_frame(self._bootstrap_method, self._universe.nilObject)
current_frame = self._interpreter.push_new_frame(self._bootstrap_method, None)
# Remember the first bytecode index, e.g. index of the halt instruction
bytecode_index = current_frame.get_bytecode_index()
......
......@@ -3,7 +3,9 @@ from rpython.rlib import jit
from som.interpreter.interpreter import Interpreter
from som.interpreter.bytecodes import Bytecodes
from som.interpreter.frame import Frame
from som.vm.symbol_table import SymbolTable
from som.vmobjects.abstract_object import AbstractObject
from som.vmobjects.object import Object
from som.vmobjects.clazz import Class
from som.vmobjects.array import Array
......@@ -12,7 +14,6 @@ from som.vmobjects.method import Method
from som.vmobjects.integer import Integer
from som.vmobjects.string import String
from som.vmobjects.block import Block, block_evaluation_primitive
from som.vmobjects.frame import Frame
from som.vmobjects.biginteger import BigInteger
from som.vmobjects.double import Double
......@@ -63,7 +64,6 @@ class Universe(object):
self.arrayClass = None
self.methodClass = None
self.symbolClass = None
self.frameClass = None
self.primitiveClass = None
self.systemClass = None
self.blockClass = None
......@@ -97,7 +97,7 @@ class Universe(object):
clazz = self.load_class(self.symbol_for(class_name))
# Lookup the invokable on class
invokable = clazz.get_class().lookup_invokable(self.symbol_for(selector))
invokable = clazz.get_class(self).lookup_invokable(self.symbol_for(selector))
bootstrap_method = self._create_bootstrap_method()
bootstrap_frame = self._create_bootstrap_frame(bootstrap_method, clazz)
......@@ -106,7 +106,7 @@ class Universe(object):
def _create_bootstrap_method(self):
# Create a fake bootstrap method to simplify later frame traversal
bootstrap_method = self.new_method(self.symbol_for("bootstrap"), 1, 0,
bootstrap_method = self.new_method(self.symbol_for("bootstrap"), 1, [],
self.new_integer(0),
self.new_integer(2))
bootstrap_method.set_bytecode(0, Bytecodes.halt)
......@@ -115,7 +115,7 @@ class Universe(object):
def _create_bootstrap_frame(self, bootstrap_method, receiver, arguments = None):
# Create a fake bootstrap frame with the system object on the stack
bootstrap_frame = self._interpreter.push_new_frame(bootstrap_method, self.nilObject)
bootstrap_frame = self._interpreter.push_new_frame(bootstrap_method, None)
bootstrap_frame.push(receiver)
if arguments:
......@@ -230,7 +230,6 @@ class Universe(object):
self.methodClass = self.new_system_class()
self.integerClass = self.new_system_class()
self.bigintegerClass = self.new_system_class()
self.frameClass = self.new_system_class()
self.primitiveClass = self.new_system_class()
self.stringClass = self.new_system_class()
self.doubleClass = self.new_system_class()
......@@ -248,7 +247,6 @@ class Universe(object):
self._initialize_system_class(self.symbolClass, self.objectClass, "Symbol")
self._initialize_system_class(self.integerClass, self.objectClass, "Integer")
self._initialize_system_class(self.bigintegerClass, self.objectClass, "BigInteger")
self._initialize_system_class(self.frameClass, self.arrayClass, "Frame")
self._initialize_system_class(self.primitiveClass, self.objectClass, "Primitive")
self._initialize_system_class(self.stringClass, self.objectClass, "String")
self._initialize_system_class(self.doubleClass, self.objectClass, "Double")
......@@ -263,7 +261,6 @@ class Universe(object):
self._load_system_class(self.symbolClass)
self._load_system_class(self.integerClass)
self._load_system_class(self.bigintegerClass)
self._load_system_class(self.frameClass)
self._load_system_class(self.primitiveClass)
self._load_system_class(self.stringClass)
self._load_system_class(self.doubleClass)
......@@ -313,12 +310,7 @@ class Universe(object):
return result
def new_array_with_length(self, length):
# Allocate a new array and set its class to be the array class
result = Array(self.nilObject, length)
result.set_class(self.arrayClass)
# Return the freshly allocated array
return result
return Array(self.nilObject, length)
def new_array_from_list(self, values):
# Allocate a new array with the same length as the list
......@@ -328,7 +320,6 @@ class Universe(object):
for i in range(len(values)):
result.set_indexable_field(i, values[i])
# Return the allocated and initialized array
return result
def new_array_with_strings(self, strings):
......@@ -339,23 +330,15 @@ class Universe(object):
for i in range(len(strings)):
result.set_indexable_field(i, self.new_string(strings[i]))
# Return the allocated and initialized array
return result
def new_block(self, method, context_frame, arguments):
# Allocate a new block and set its class to be the block class
result = Block(self.nilObject, method, context_frame)
result.set_class(self._get_block_class(arguments))
# Return the freshly allocated block
return result
return Block(method, context_frame)
def new_class(self, class_class):
# Allocate a new class and set its class to be the given class class
result = Class(self, class_class.get_number_of_instance_fields())
result.set_class(class_class)
# Return the freshly allocated class
return result
def new_frame(self, previous_frame, method, context):
......@@ -366,65 +349,31 @@ class Universe(object):
method.get_number_of_locals().get_embedded_integer() +
method.get_maximum_number_of_stack_elements().get_embedded_integer() + 2)
# Allocate a new frame and set its class to be the frame class
result = Frame(self.nilObject, length, method, context, previous_frame)
result.set_class(self.frameClass)