javaclass

Changeset

31:bdd29da1e141
2004-11-11 Paul Boddie raw files shortlog changelog graph Modified invokespecial to hopefully find the appropriate methods to use in each invocation case. Added SLICE+1.
bytecode.py (file)
     1.1 --- a/bytecode.py	Thu Nov 11 16:48:41 2004 +0100
     1.2 +++ b/bytecode.py	Thu Nov 11 16:49:35 2004 +0100
     1.3 @@ -399,6 +399,10 @@
     1.4          self.output.append(opmap["UNARY_NEGATIVE"])
     1.5          self.position += 1
     1.6  
     1.7 +    def slice_1(self):
     1.8 +        self.output.append(opmap["SLICE+1"])
     1.9 +        self.position += 1
    1.10 +
    1.11      def compare_op(self, op):
    1.12          self.output.append(opmap["COMPARE_OP"])
    1.13          self.position += 1
    1.14 @@ -1266,48 +1270,75 @@
    1.15          # Get the number of parameters from the descriptor.
    1.16          count = len(target.get_descriptor()[0])
    1.17  
    1.18 -        # Check for the method name and invoke superclasses where appropriate.
    1.19 -        # NOTE: This may not be a sufficient test.
    1.20 -        if str(self.method.get_python_name()) == str(target_name):
    1.21 -            program.build_tuple(count + 1)  # Stack: tuple
    1.22 -            # Must use the actual class.
    1.23 -            # NOTE: Verify this.
    1.24 -            program.load_global(str(self.class_file.this_class.get_python_name()))
    1.25 -                                            # Stack: tuple, classref
    1.26 -            program.load_attr("__bases__")  # Stack: tuple, bases
    1.27 -            program.dup_top()               # Stack: tuple, bases, bases
    1.28 -            program.load_global("len")      # Stack: tuple, bases, bases, len
    1.29 -            program.rot_two()               # Stack: tuple, bases, len, bases
    1.30 -            program.call_function(1)        # Stack: tuple, bases, #bases
    1.31 -            program.load_const(0)           # Stack: tuple, bases, #bases, 0
    1.32 -            program.compare_op("==")        # Stack: tuple, bases, result
    1.33 -            program.jump_to_label(1, "next")
    1.34 -            program.pop_top()               # Stack: tuple, bases
    1.35 -            program.load_const(0)           # Stack: tuple, bases, 0
    1.36 -            program.binary_subscr()         # Stack: tuple, bases[0]
    1.37 +        # The stack may contain one of the following patterns:
    1.38 +        # Stack: classref, arg1, arg2, ...
    1.39 +        # Stack: objectref, arg1, arg2, ...
    1.40 +        # method == __init__, classref -> classref(arg1, arg2, ...)
    1.41 +        # method == __init__, objectref == self -> cls.bases[0].__init__(objectref, arg1, arg2, ...)
    1.42 +        # method == __init__, objectref != self -> should not occur
    1.43 +        # method != __init__, classref -> classref.method(classref, arg1, arg2, ...)
    1.44 +        # method != __init__, objectref == self -> cls.bases[0].method(objectref, arg1, arg2, ...)
    1.45 +        # method != __init__, objectref != self -> should not occur
    1.46 +
    1.47 +        # First, we build a tuple of the reference and arguments.
    1.48 +        program.build_tuple(count + 1)  # Stack: tuple
    1.49 +
    1.50 +        # Then, we test the nature of the reference.
    1.51 +        program.dup_top()               # Stack: tuple, tuple
    1.52 +        program.load_const(0)           # Stack: tuple, tuple, 0
    1.53 +        program.binary_subscr()         # Stack: tuple, reference
    1.54 +        program.dup_top()               # Stack: tuple, reference, reference
    1.55 +
    1.56 +        # Is it self?
    1.57 +        program.load_fast(0)            # Stack: tuple, reference, reference, self
    1.58 +        program.compare_op("is")        # Stack: tuple, reference, result
    1.59 +        program.jump_to_label(1, "is-self")
    1.60 +        program.pop_top()               # Stack: tuple, reference
    1.61 +
    1.62 +        # Is another class or reference.
    1.63 +        # NOTE: Reference case not covered!
    1.64 +        if str(target_name) == "__init__":
    1.65 +            program.rot_two()               # Stack: reference, tuple
    1.66 +            program.load_const(1)           # Stack: reference, tuple, 1
    1.67 +            program.slice_1()               # Stack: reference, tuple[1:]
    1.68 +            program.load_global("apply")    # Stack: reference, tuple, apply
    1.69 +            program.rot_three()             # Stack: apply, reference, tuple
    1.70 +            program.call_function(2)
    1.71 +            # NOTE: Combinations of new, dup tend to produce interfering extra
    1.72 +            # NOTE: class references.
    1.73 +            program.rot_two()               # Stack: objectref, classref
    1.74 +            program.pop_top()
    1.75 +            program.jump_to_label(None, "done")
    1.76 +        else:
    1.77              self._invoke(target_name, program)
    1.78 -            program.jump_to_label(None, "next2")
    1.79 -            program.start_label("next")
    1.80 -            program.pop_top()               # Stack: tuple, bases
    1.81 -            program.pop_top()               # Stack: tuple
    1.82 -            program.pop_top()               # Stack:
    1.83 -            program.start_label("next2")
    1.84 +            program.jump_to_label(None, "done")
    1.85  
    1.86 -        # Initialisation outside an initialisation method.
    1.87 -        elif str(target_name) == "__init__":
    1.88 -            # NOTE: Due to changes with the new instruction's implementation, the
    1.89 -            # NOTE: stack differs from that stated: objectref, arg1, arg2, ...
    1.90 -            # Stack: classref, arg1, arg2, ...
    1.91 -            program.build_tuple(count)          # Stack: classref, tuple
    1.92 -                                                # NOTE: Stack: objectref, tuple
    1.93 -            program.load_global("apply")        # Stack: classref, tuple, apply
    1.94 -            program.rot_three()                 # Stack: apply, classref, tuple
    1.95 -            program.call_function(2)
    1.96 +        # Is self.
    1.97 +        program.start_label("is-self")
    1.98 +        program.pop_top()               # Stack: tuple, reference
    1.99 +        program.pop_top()               # Stack: tuple
   1.100 +        program.load_global(str(self.class_file.this_class.get_python_name()))
   1.101 +                                        # Stack: tuple, classref
   1.102 +        program.load_attr("__bases__")  # Stack: tuple, bases
   1.103 +        program.dup_top()               # Stack: tuple, bases, bases
   1.104 +        program.load_global("len")      # Stack: tuple, bases, bases, len
   1.105 +        program.rot_two()               # Stack: tuple, bases, len, bases
   1.106 +        program.call_function(1)        # Stack: tuple, bases, #bases
   1.107 +        program.load_const(0)           # Stack: tuple, bases, #bases, 0
   1.108 +        program.compare_op("==")        # Stack: tuple, bases, result
   1.109 +        program.jump_to_label(1, "no-bases")
   1.110 +        program.pop_top()               # Stack: tuple, bases
   1.111 +        program.load_const(0)           # Stack: tuple, bases, 0
   1.112 +        program.binary_subscr()         # Stack: tuple, bases[0]
   1.113 +        self._invoke(target_name, program)
   1.114 +        program.jump_to_label(None, "done")
   1.115  
   1.116 -        else:
   1.117 -            program.build_tuple(count)          # Stack: objectref, tuple
   1.118 -            program.rot_two()                   # Stack: tuple, objectref
   1.119 -            self._invoke(target_name, program)
   1.120 +        # No bases found, do no invocation.
   1.121 +        program.start_label("no-bases")
   1.122 +        program.pop_top()               # Stack: tuple, bases
   1.123 +        program.pop_top()               # Stack: tuple
   1.124 +        program.pop_top()               # Stack:
   1.125 +        program.start_label("done")
   1.126  
   1.127      """
   1.128      def invokespecial(self, arguments, program):