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

3
from som.vmobjects.array import Array
Stefan Marr's avatar
Stefan Marr committed
4

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

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

Stefan Marr's avatar
Stefan Marr committed
18
    
19 20 21 22 23 24 25 26 27 28 29 30
    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)
31
        
Stefan Marr's avatar
Stefan Marr committed
32 33 34
    
    def is_primitive(self):
        return False
35 36 37 38 39 40
    
    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
41 42 43
  
    def get_number_of_locals(self):
        # Get the number of locals (converted to a Java integer)
44
        return self._number_of_locals
Stefan Marr's avatar
Stefan Marr committed
45 46 47

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

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

55
    def _set_signature(self, value):
Stefan Marr's avatar
Stefan Marr committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69
        # 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()):
70
            if self.get_indexable_field(i).is_invokable():
Stefan Marr's avatar
Stefan Marr committed
71 72 73 74 75 76 77 78 79 80
                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()
  
81
    def _get_default_number_of_fields(self):
Stefan Marr's avatar
Stefan Marr committed
82 83 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)

    def get_bytecode(self, index):
        # Get the bytecode at the given index
91
        return ord(self._bytecodes[index])
Stefan Marr's avatar
Stefan Marr committed
92 93 94

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

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

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

    def get_inline_cache_class(self, bytecode_index):
        return self._inline_cache_class[bytecode_index]

    def get_inline_cache_invokable(self, bytecode_index):
        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
116 117 118 119 120

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