method.py 5.06 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
    # XXX this means that the JIT doesn't see changes to the method object
    @jit.elidable_promote('all')
Stefan Marr's avatar
Stefan Marr committed
54 55 56 57 58
    def get_signature(self):
        # Get the signature of this method by reading the field with signature
        # index
        return self.get_field(self.SIGNATURE_INDEX)

59
    def _set_signature(self, value):
Stefan Marr's avatar
Stefan Marr committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73
        # 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()):
74
            if self.get_indexable_field(i).is_invokable():
Stefan Marr's avatar
Stefan Marr committed
75 76
                self.get_indexable_field(i).set_holder(value)

77 78
    # XXX this means that the JIT doesn't see changes to the constants
    @jit.elidable_promote('all')
Stefan Marr's avatar
Stefan Marr committed
79 80 81 82 83 84 85 86
    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()
  
87
    def _get_default_number_of_fields(self):
Stefan Marr's avatar
Stefan Marr committed
88 89 90 91 92 93 94
        # 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)

95
    @jit.elidable_promote('all')
Stefan Marr's avatar
Stefan Marr committed
96 97
    def get_bytecode(self, index):
        # Get the bytecode at the given index
98
        assert 0 <= index and index < len(self._bytecodes)
99
        return ord(self._bytecodes[index])
Stefan Marr's avatar
Stefan Marr committed
100 101 102

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

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

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

115
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
116
    def get_inline_cache_class(self, bytecode_index):
117
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_class)
Stefan Marr's avatar
Stefan Marr committed
118 119
        return self._inline_cache_class[bytecode_index]

120
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
121
    def get_inline_cache_invokable(self, bytecode_index):
122
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_invokable)
Stefan Marr's avatar
Stefan Marr committed
123 124 125 126 127
        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
128 129 130 131 132

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