Commit 54182a5d authored by Stefan Marr's avatar Stefan Marr

Merge pull request #1 from cfbolz/master

Optimize low-hanging fruit in the jitted RPython version
parents 3558b9f8 18ad30f8
This diff is collapsed.
from rpython.rlib.rrandom import Random from rpython.rlib.rrandom import Random
from rpython.rlib import jit
from som.interpreter.interpreter import Interpreter from som.interpreter.interpreter import Interpreter
from som.interpreter.bytecodes import Bytecodes from som.interpreter.bytecodes import Bytecodes
...@@ -26,14 +27,29 @@ import time ...@@ -26,14 +27,29 @@ import time
from rlib.exit import Exit from rlib.exit import Exit
from rlib.osext import path_split from rlib.osext import path_split
class GlobalVersion(object):
pass
class Universe(object): class Universe(object):
_immutable_fields_ = [
"nilObject",
"trueObject",
"falseObject",
"objectClass",
"integerClass",
"doubleClass",
"primitiveClass",
"_global_version?",
]
def __init__(self, avoid_exit = False): def __init__(self, avoid_exit = False):
self._interpreter = Interpreter(self) self._interpreter = Interpreter(self)
self._symbol_table = SymbolTable() self._symbol_table = SymbolTable()
self._globals = {} self._globals = {}
self._global_version = GlobalVersion()
self.nilObject = None self.nilObject = None
self.trueObject = None self.trueObject = None
self.falseObject = None self.falseObject = None
...@@ -51,6 +67,7 @@ class Universe(object): ...@@ -51,6 +67,7 @@ class Universe(object):
self.primitiveClass = None self.primitiveClass = None
self.systemClass = None self.systemClass = None
self.blockClass = None self.blockClass = None
self.blockClasses = None
self.stringClass = None self.stringClass = None
self.doubleClass = None self.doubleClass = None
...@@ -279,7 +296,10 @@ class Universe(object): ...@@ -279,7 +296,10 @@ class Universe(object):
self.set_global( trueClassName, trueClass) self.set_global( trueClassName, trueClass)
self.set_global(falseClassName, falseClass) self.set_global(falseClassName, falseClass)
self.blockClasses = [self.blockClass] + \
[self._make_block_class(i) for i in [1, 2, 3]]
return system_object return system_object
def symbol_for(self, string): def symbol_for(self, string):
...@@ -474,35 +494,31 @@ class Universe(object): ...@@ -474,35 +494,31 @@ class Universe(object):
def get_global(self, name): def get_global(self, name):
# Return the global with the given name if it's in the dictionary of globals # Return the global with the given name if it's in the dictionary of globals
if self.has_global(name): # if not, return None
return self._globals[name] jit.promote(self)
return self._get_global(name, self._global_version)
# Global not found @jit.elidable
return None def _get_global(self, name, version):
return self._globals.get(name, None)
def set_global(self, name, value): def set_global(self, name, value):
# Insert the given value into the dictionary of globals # Insert the given value into the dictionary of globals
self._globals[name] = value self._globals[name] = value
self._global_version = GlobalVersion()
def has_global(self, name): def has_global(self, name):
# Returns if the universe has a value for the global of the given name # Returns if the universe has a value for the global of the given name
return name in self._globals return name in self._globals
def _get_block_class(self, number_of_arguments = None): def _get_block_class(self, number_of_arguments):
if not number_of_arguments: return self.blockClasses[number_of_arguments]
# Get the generic block class
return self.blockClass def _make_block_class(self, number_of_arguments):
# Compute the name of the block class with the given number of # Compute the name of the block class with the given number of
# arguments # arguments
name = self.symbol_for("Block" + str(number_of_arguments)) name = self.symbol_for("Block" + str(number_of_arguments))
# Lookup the specific block class in the dictionary of globals and
# return it
if self.has_global(name):
return self.get_global(name)
# Get the block class for blocks with the given number of arguments # Get the block class for blocks with the given number of arguments
result = self._load_class(name, None) result = self._load_class(name, None)
...@@ -517,8 +533,9 @@ class Universe(object): ...@@ -517,8 +533,9 @@ class Universe(object):
def load_class(self, name): def load_class(self, name):
# Check if the requested class is already in the dictionary of globals # Check if the requested class is already in the dictionary of globals
if self.has_global(name): result = self.get_global(name)
return self.get_global(name) if result is not None:
return result
# Load the class # Load the class
result = self._load_class(name, None) result = self._load_class(name, None)
......
from rpython.rlib import jit
from som.vmobjects.object import Object from som.vmobjects.object import Object
from som.vmobjects.primitive import Primitive from som.vmobjects.primitive import Primitive
...@@ -15,7 +17,7 @@ class Block(Object): ...@@ -15,7 +17,7 @@ class Block(Object):
def get_method(self): def get_method(self):
# Get the method of this block by reading the field with method index # Get the method of this block by reading the field with method index
return self._method return jit.promote(self._method)
def get_context(self): def get_context(self):
# Get the context of this block by reading the field with context index # Get the context of this block by reading the field with context index
...@@ -26,6 +28,7 @@ class Block(Object): ...@@ -26,6 +28,7 @@ class Block(Object):
return self.NUMBER_OF_BLOCK_FIELDS return self.NUMBER_OF_BLOCK_FIELDS
class Evaluation(Primitive): class Evaluation(Primitive):
_immutable_fields_ = ['_number_of_arguments']
def __init__(self, num_args, universe, invoke): def __init__(self, num_args, universe, invoke):
Primitive.__init__(self, self._compute_signature_string(num_args), Primitive.__init__(self, self._compute_signature_string(num_args),
universe, invoke) universe, invoke)
......
...@@ -17,13 +17,12 @@ class Frame(Array): ...@@ -17,13 +17,12 @@ class Frame(Array):
# Static field indices and number of frame fields # Static field indices and number of frame fields
NUMBER_OF_FRAME_FIELDS = Array.NUMBER_OF_OBJECT_FIELDS NUMBER_OF_FRAME_FIELDS = Array.NUMBER_OF_OBJECT_FIELDS
_immutable_fields_ = ["_method", "_context", "_previous_frame"] _immutable_fields_ = ["_method", "_context"]
def __init__(self, nilObject, num_elements, method, context, previous_frame): def __init__(self, nilObject, num_elements, method, context, previous_frame):
Array.__init__(self, nilObject, num_elements) Array.__init__(self, nilObject, num_elements)
self._stack_pointer = 0 self._stack_pointer = 0
self._bytecode_index = 0 self._bytecode_index = 0
self._local_offset = 0
self._method = method self._method = method
self._context = context self._context = context
self._previous_frame = previous_frame if previous_frame else nilObject self._previous_frame = previous_frame if previous_frame else nilObject
...@@ -62,6 +61,7 @@ class Frame(Array): ...@@ -62,6 +61,7 @@ class Frame(Array):
# Return the found context # Return the found context
return frame return frame
@jit.unroll_safe
def get_outer_context(self, nilObject): def get_outer_context(self, nilObject):
# Compute the outer context of this frame # Compute the outer context of this frame
frame = self frame = self
...@@ -77,6 +77,9 @@ class Frame(Array): ...@@ -77,6 +77,9 @@ class Frame(Array):
# Get the method by reading the field with method index # Get the method by reading the field with method index
return self._method return self._method
def get_number_of_arguments(self):
return self.get_method().get_number_of_arguments()
def _get_default_number_of_fields(self): def _get_default_number_of_fields(self):
# Return the default number of fields in a frame # Return the default number of fields in a frame
return self.NUMBER_OF_FRAME_FIELDS return self.NUMBER_OF_FRAME_FIELDS
...@@ -95,7 +98,7 @@ class Frame(Array): ...@@ -95,7 +98,7 @@ class Frame(Array):
def get_stack_pointer(self): def get_stack_pointer(self):
# Get the current stack pointer for this frame # Get the current stack pointer for this frame
return self._stack_pointer return jit.promote(self._stack_pointer)
def set_stack_pointer(self, value): def set_stack_pointer(self, value):
# Set the current stack pointer for this frame # Set the current stack pointer for this frame
...@@ -103,10 +106,9 @@ class Frame(Array): ...@@ -103,10 +106,9 @@ class Frame(Array):
def reset_stack_pointer(self): def reset_stack_pointer(self):
# arguments are stored in front of local variables # arguments are stored in front of local variables
self._local_offset = self.get_method().get_number_of_arguments()
# Set the stack pointer to its initial value thereby clearing the stack # Set the stack pointer to its initial value thereby clearing the stack
self.set_stack_pointer(self._local_offset + self.set_stack_pointer(self.get_number_of_arguments() +
self.get_method().get_number_of_locals().get_embedded_integer() - 1) self.get_method().get_number_of_locals().get_embedded_integer() - 1)
def get_bytecode_index(self): def get_bytecode_index(self):
...@@ -128,10 +130,10 @@ class Frame(Array): ...@@ -128,10 +130,10 @@ class Frame(Array):
self.set_indexable_field(self.get_stack_pointer() - index, value) self.set_indexable_field(self.get_stack_pointer() - index, value)
def _get_local(self, index): def _get_local(self, index):
return self.get_indexable_field(self._local_offset + index) return self.get_indexable_field(self.get_number_of_arguments() + index)
def _set_local(self, index, value): def _set_local(self, index, value):
self.set_indexable_field(self._local_offset + index, value) self.set_indexable_field(self.get_number_of_arguments() + index, value)
def get_local(self, index, context_level): def get_local(self, index, context_level):
# Get the local with the given index in the given context # Get the local with the given index in the given context
......
...@@ -49,6 +49,8 @@ class Method(Array): ...@@ -49,6 +49,8 @@ class Method(Array):
# Get the maximum number of stack elements # Get the maximum number of stack elements
return self._maximum_number_of_stack_elements return self._maximum_number_of_stack_elements
# XXX this means that the JIT doesn't see changes to the method object
@jit.elidable_promote('all')
def get_signature(self): def get_signature(self):
# Get the signature of this method by reading the field with signature # Get the signature of this method by reading the field with signature
# index # index
...@@ -72,6 +74,8 @@ class Method(Array): ...@@ -72,6 +74,8 @@ class Method(Array):
if self.get_indexable_field(i).is_invokable(): if self.get_indexable_field(i).is_invokable():
self.get_indexable_field(i).set_holder(value) self.get_indexable_field(i).set_holder(value)
# XXX this means that the JIT doesn't see changes to the constants
@jit.elidable_promote('all')
def get_constant(self, bytecode_index): def get_constant(self, bytecode_index):
# Get the constant associated to a given bytecode index # Get the constant associated to a given bytecode index
return self.get_indexable_field(self.get_bytecode(bytecode_index + 1)) return self.get_indexable_field(self.get_bytecode(bytecode_index + 1))
...@@ -88,7 +92,7 @@ class Method(Array): ...@@ -88,7 +92,7 @@ class Method(Array):
# Get the number of bytecodes in this method # Get the number of bytecodes in this method
return len(self._bytecodes) return len(self._bytecodes)
@jit.elidable @jit.elidable_promote('all')
def get_bytecode(self, index): def get_bytecode(self, index):
# Get the bytecode at the given index # Get the bytecode at the given index
assert 0 <= index and index < len(self._bytecodes) assert 0 <= index and index < len(self._bytecodes)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment