method.py 4.84 KB
Newer Older
Stefan Marr's avatar
Stefan Marr committed
1 2
from __future__ import absolute_import

3 4
from rpython.rlib import jit

5
from som.vmobjects.array import Array
Stefan Marr's avatar
Stefan Marr committed
6

7
class Method(Array):
Stefan Marr's avatar
Stefan Marr committed
8 9
    
    # Static field indices and number of method fields
10
    SIGNATURE_INDEX                 = Array.NUMBER_OF_OBJECT_FIELDS
11 12
    HOLDER_INDEX                    = 1 + SIGNATURE_INDEX
    NUMBER_OF_METHOD_FIELDS         = 1 + HOLDER_INDEX
Stefan Marr's avatar
Stefan Marr committed
13

14 15 16 17 18 19
    _immutable_fields_ = ["_bytecodes[*]",
                          "_inline_cache_class",
                          "_receiver_class_table",
                          "_number_of_locals",
                          "_maximum_number_of_stack_elements"]

Stefan Marr's avatar
Stefan Marr committed
20
    
21 22 23 24 25 26 27 28 29 30 31 32
    def __init__(self, nilObject, num_literals, num_locals, max_stack_elements,
                 num_bytecodes, signature):
        Array.__init__(self, nilObject, num_literals)

        # Set the number of bytecodes in this method
        self._bytecodes              = ["\x00"] * num_bytecodes
        self._inline_cache_class     = [None]   * num_bytecodes
        self._inline_cache_invokable = [None]   * num_bytecodes
        
        self._number_of_locals       = num_locals
        self._maximum_number_of_stack_elements = max_stack_elements
        self._set_signature(signature)
33
        
Stefan Marr's avatar
Stefan Marr committed
34 35 36
    
    def is_primitive(self):
        return False
37 38 39 40 41 42
    
    def is_invokable(self):
        """In the RPython version, we use this method to identify methods 
           and primitives
        """
        return True
Stefan Marr's avatar
Stefan Marr committed
43 44
  
    def get_number_of_locals(self):
45
        # Get the number of locals
46
        return self._number_of_locals
Stefan Marr's avatar
Stefan Marr committed
47 48 49

    def get_maximum_number_of_stack_elements(self):
        # Get the maximum number of stack elements
50
        return self._maximum_number_of_stack_elements
Stefan Marr's avatar
Stefan Marr committed
51 52 53 54 55 56

    def get_signature(self):
        # Get the signature of this method by reading the field with signature
        # index
        return self.get_field(self.SIGNATURE_INDEX)

57
    def _set_signature(self, value):
Stefan Marr's avatar
Stefan Marr committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71
        # Set the signature of this method by writing to the field with
        # signature index
        self.set_field(self.SIGNATURE_INDEX, value)

    def get_holder(self):
        # Get the holder of this method by reading the field with holder index
        return self.get_field(self.HOLDER_INDEX)

    def set_holder(self, value):
        # Set the holder of this method by writing to the field with holder index
        self.set_field(self.HOLDER_INDEX, value)

        # Make sure all nested invokables have the same holder
        for i in range(0, self.get_number_of_indexable_fields()):
72
            if self.get_indexable_field(i).is_invokable():
Stefan Marr's avatar
Stefan Marr committed
73 74 75 76 77 78 79 80 81 82
                self.get_indexable_field(i).set_holder(value)

    def get_constant(self, bytecode_index):
        # Get the constant associated to a given bytecode index
        return self.get_indexable_field(self.get_bytecode(bytecode_index + 1))

    def get_number_of_arguments(self):
        # Get the number of arguments of this method
        return self.get_signature().get_number_of_signature_arguments()
  
83
    def _get_default_number_of_fields(self):
Stefan Marr's avatar
Stefan Marr committed
84 85 86 87 88 89 90
        # Return the default number of fields in a method
        return self.NUMBER_OF_METHOD_FIELDS
  
    def get_number_of_bytecodes(self):
        # Get the number of bytecodes in this method
        return len(self._bytecodes)

91
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
92 93
    def get_bytecode(self, index):
        # Get the bytecode at the given index
94
        assert 0 <= index and index < len(self._bytecodes)
95
        return ord(self._bytecodes[index])
Stefan Marr's avatar
Stefan Marr committed
96 97 98

    def set_bytecode(self, index, value):
        # Set the bytecode at the given index to the given value
99 100
        assert 0 <= value and value <= 255
        self._bytecodes[index] = chr(value)
Stefan Marr's avatar
Stefan Marr committed
101 102 103

    def invoke(self, frame, interpreter):
        # Allocate and push a new frame on the interpreter stack
104 105
        new_frame = interpreter.push_new_frame(self,
                                    interpreter.get_universe().nilObject)
Stefan Marr's avatar
Stefan Marr committed
106 107 108 109 110
        new_frame.copy_arguments_from(frame)

    def __str__(self):
        return "Method(" + self.get_holder().get_name().get_string() + ">>" + str(self.get_signature()) + ")"

111
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
112
    def get_inline_cache_class(self, bytecode_index):
113
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_class)
Stefan Marr's avatar
Stefan Marr committed
114 115
        return self._inline_cache_class[bytecode_index]

116
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
117
    def get_inline_cache_invokable(self, bytecode_index):
118
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_invokable)
Stefan Marr's avatar
Stefan Marr committed
119 120 121 122 123
        return self._inline_cache_invokable[bytecode_index]

    def set_inline_cache(self, bytecode_index, receiver_class, invokable):
        self._inline_cache_class[bytecode_index]    = receiver_class
        self._inline_cache_invokable[bytecode_index] = invokable
124 125 126 127 128

    def merge_point_string(self):
        """ debug info for the jit """
        return "%s>>%s" % (self.get_holder().get_name().get_string(),
                           self.get_signature().get_string())