method.py 4.32 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.abstract_object import AbstractObject
Stefan Marr's avatar
Stefan Marr committed
6

7
class Method(AbstractObject):
Stefan Marr's avatar
Stefan Marr committed
8
    
9
    _immutable_fields_ = ["_bytecodes[*]",
10
                          "_literals[*]",
11 12 13
                          "_inline_cache_class",
                          "_receiver_class_table",
                          "_number_of_locals",
14 15
                          "_maximum_number_of_stack_elements",
                          "_signature"]
16

Stefan Marr's avatar
Stefan Marr committed
17
    
18
    def __init__(self, literals, num_locals, max_stack_elements,
19
                 num_bytecodes, signature):
20
        AbstractObject.__init__(self)
21 22 23 24 25 26

        # 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
        
27 28
        self._literals               = literals
        
29 30
        self._number_of_locals       = num_locals
        self._maximum_number_of_stack_elements = max_stack_elements
31 32 33
        self._signature = signature
        
        self._holder = None
34
        
Stefan Marr's avatar
Stefan Marr committed
35 36 37
    
    def is_primitive(self):
        return False
38 39 40 41 42 43
    
    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
44 45
  
    def get_number_of_locals(self):
46
        # Get the number of locals
47
        return self._number_of_locals
Stefan Marr's avatar
Stefan Marr committed
48 49 50

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

53 54
    # 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
55
    def get_signature(self):
56
        return self._signature
Stefan Marr's avatar
Stefan Marr committed
57 58

    def get_holder(self):
59
        return self._holder
Stefan Marr's avatar
Stefan Marr committed
60 61

    def set_holder(self, value):
62
        self._holder = value
Stefan Marr's avatar
Stefan Marr committed
63 64

        # Make sure all nested invokables have the same holder
65 66 67
        for i in range(0, len(self._literals)):
            if self._literals[i].is_invokable():
                self._literals[i].set_holder(value)
Stefan Marr's avatar
Stefan Marr committed
68

69 70
    # XXX this means that the JIT doesn't see changes to the constants
    @jit.elidable_promote('all')
Stefan Marr's avatar
Stefan Marr committed
71 72
    def get_constant(self, bytecode_index):
        # Get the constant associated to a given bytecode index
73
        return self._literals[self.get_bytecode(bytecode_index + 1)]
Stefan Marr's avatar
Stefan Marr committed
74 75 76 77

    def get_number_of_arguments(self):
        # Get the number of arguments of this method
        return self.get_signature().get_number_of_signature_arguments()
78
    
Stefan Marr's avatar
Stefan Marr committed
79 80 81 82
    def get_number_of_bytecodes(self):
        # Get the number of bytecodes in this method
        return len(self._bytecodes)

83
    @jit.elidable_promote('all')
Stefan Marr's avatar
Stefan Marr committed
84 85
    def get_bytecode(self, index):
        # Get the bytecode at the given index
86
        assert 0 <= index and index < len(self._bytecodes)
87
        return ord(self._bytecodes[index])
Stefan Marr's avatar
Stefan Marr committed
88 89 90

    def set_bytecode(self, index, value):
        # Set the bytecode at the given index to the given value
91 92
        assert 0 <= value and value <= 255
        self._bytecodes[index] = chr(value)
Stefan Marr's avatar
Stefan Marr committed
93 94 95

    def invoke(self, frame, interpreter):
        # Allocate and push a new frame on the interpreter stack
96
        new_frame = interpreter.push_new_frame(self, None)
Stefan Marr's avatar
Stefan Marr committed
97 98 99 100
        new_frame.copy_arguments_from(frame)

    def __str__(self):
        return "Method(" + self.get_holder().get_name().get_string() + ">>" + str(self.get_signature()) + ")"
101 102 103
    
    def get_class(self, universe):
        return universe.methodClass
Stefan Marr's avatar
Stefan Marr committed
104

105
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
106
    def get_inline_cache_class(self, bytecode_index):
107
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_class)
Stefan Marr's avatar
Stefan Marr committed
108 109
        return self._inline_cache_class[bytecode_index]

110
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
111
    def get_inline_cache_invokable(self, bytecode_index):
112
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_invokable)
Stefan Marr's avatar
Stefan Marr committed
113 114 115 116 117
        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
118 119 120 121 122

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