method.py 5.03 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 6
from som.interpreter.control_flow import ReturnException, RestartLoopException

7
from som.vmobjects.abstract_object import AbstractObject
Stefan Marr's avatar
Stefan Marr committed
8

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

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

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

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

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

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

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

        # Make sure all nested invokables have the same holder
67 68 69
        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
70

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

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

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

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

    def invoke(self, frame, interpreter):
        # Allocate and push a new frame on the interpreter stack
98
        new_frame = interpreter.new_frame(frame, self, None)
Stefan Marr's avatar
Stefan Marr committed
99
        new_frame.copy_arguments_from(frame)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
        
        while True:
            try:
                result = interpreter.interpret(self, new_frame)
                frame.pop_old_arguments_and_push_result(self, result)
                new_frame.clear_previous_frame()
                return
            except ReturnException as e:
                if e.has_reached_target(new_frame):
                    frame.pop_old_arguments_and_push_result(self, e.get_result())
                    return
                else:
                    new_frame.clear_previous_frame()
                    raise e
            except RestartLoopException:
                new_frame.reset_stack_pointer()
Stefan Marr's avatar
Stefan Marr committed
116 117 118

    def __str__(self):
        return "Method(" + self.get_holder().get_name().get_string() + ">>" + str(self.get_signature()) + ")"
119 120 121
    
    def get_class(self, universe):
        return universe.methodClass
Stefan Marr's avatar
Stefan Marr committed
122

123
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
124
    def get_inline_cache_class(self, bytecode_index):
125
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_class)
Stefan Marr's avatar
Stefan Marr committed
126 127
        return self._inline_cache_class[bytecode_index]

128
    @jit.elidable
Stefan Marr's avatar
Stefan Marr committed
129
    def get_inline_cache_invokable(self, bytecode_index):
130
        assert 0 <= bytecode_index and bytecode_index < len(self._inline_cache_invokable)
Stefan Marr's avatar
Stefan Marr committed
131 132 133 134 135
        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
136 137 138 139 140

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