javaclass

Changeset

66:0091c7d9b220
2004-11-20 Paul Boddie raw files shortlog changelog graph Changed the new implementation to use object.__new__ and root classes to inherit from object. Changed static and class initialisation methods to be static methods. Harmonised invokespecial and invokestatic. Fixed/improved ldc, ldc_w.
bytecode.py (file)
     1.1 --- a/bytecode.py	Sat Nov 20 21:41:45 2004 +0100
     1.2 +++ b/bytecode.py	Sat Nov 20 21:46:33 2004 +0100
     1.3 @@ -1364,6 +1364,8 @@
     1.4          # Stack: objectref, arg1, arg2, ...
     1.5          program.build_tuple(count)          # Stack: objectref, tuple
     1.6          program.rot_two()                   # Stack: tuple, objectref
     1.7 +        # NOTE: The interface information is not used to discover the correct
     1.8 +        # NOTE: method.
     1.9          self._invoke(target_name, program)
    1.10  
    1.11      def invokespecial(self, arguments, program):
    1.12 @@ -1374,87 +1376,21 @@
    1.13          target = self.class_file.constants[index - 1]
    1.14          original_name = target.get_name()
    1.15          target_name = target.get_python_name()
    1.16 -        method_name = self.method.get_name()
    1.17 -
    1.18          # Get the number of parameters from the descriptor.
    1.19 -
    1.20          count = len(target.get_descriptor()[0])
    1.21 -
    1.22 -        # The stack may contain one of the following patterns:
    1.23 -        # Stack: classref, arg1, arg2, ...
    1.24 -        # Stack: objectref, arg1, arg2, ...
    1.25 -        # method == __init__, classref -> classref(arg1, arg2, ...)
    1.26 -        # method == __init__, objectref == self -> cls.bases[0].__init__(objectref, arg1, arg2, ...)
    1.27 -        # method == __init__, objectref != self -> should not occur
    1.28 -        # method != __init__, classref -> classref.method(classref, arg1, arg2, ...)
    1.29 -        # method != __init__, objectref == self -> cls.bases[0].method(objectref, arg1, arg2, ...)
    1.30 -        # method != __init__, objectref != self -> should not occur
    1.31 -
    1.32          # First, we build a tuple of the reference and arguments.
    1.33 -
    1.34 -        program.build_tuple(count + 1)  # Stack: tuple
    1.35 -
    1.36 -        # Then, we test the nature of the reference.
    1.37 -
    1.38 -        program.dup_top()               # Stack: tuple, tuple
    1.39 -        program.load_const(0)           # Stack: tuple, tuple, 0
    1.40 -        program.binary_subscr()         # Stack: tuple, reference
    1.41 -
    1.42 -        # Is it self?
    1.43 -
    1.44 -        program.dup_top()               # Stack: tuple, reference, reference
    1.45 -        program.load_fast(0)            # Stack: tuple, reference, reference, self|cls
    1.46 -        program.compare_op("is")        # Stack: tuple, reference, result
    1.47 -        program.jump_to_label(1, "is-self")
    1.48 -        program.pop_top()               # Stack: tuple, reference
    1.49 -
    1.50 -        # Is another class or reference.
    1.51 -        # NOTE: Reference case not covered!
    1.52 -
    1.53 +        program.build_tuple(count + 1)      # Stack: tuple
    1.54 +        # Get the class name instead of the fully qualified name.
    1.55 +        # NOTE: Do proper resolution of classes,
    1.56 +        # NOTE: Not bothering with Object initialisation.
    1.57 +        full_class_name = target.get_class().get_python_name()
    1.58 +        if full_class_name != "java.lang.Object":
    1.59 +            class_name = full_class_name.split(".")[-1]
    1.60 +            program.load_global(class_name) # Stack: tuple, classref
    1.61 +            self._invoke(target_name, program)
    1.62 +        # Remove Python None return value.
    1.63          if str(original_name) == "<init>":
    1.64 -            program.rot_two()               # Stack: reference, tuple
    1.65 -            program.load_const(1)           # Stack: reference, tuple, 1
    1.66 -            program.slice_1()               # Stack: reference, tuple[1:]
    1.67 -            program.call_function_var(0)    # Stack: result
    1.68 -            # NOTE: Combinations of new, dup tend to produce interfering extra
    1.69 -            # NOTE: class references.
    1.70 -            program.rot_two()               # Stack: objectref, classref
    1.71              program.pop_top()
    1.72 -            program.jump_to_label(None, "done")
    1.73 -        else:
    1.74 -            self._invoke(target_name, program)
    1.75 -            program.jump_to_label(None, "done")
    1.76 -
    1.77 -        # Is self.
    1.78 -
    1.79 -        program.start_label("is-self")
    1.80 -        program.pop_top()               # Stack: tuple, reference
    1.81 -        program.pop_top()               # Stack: tuple
    1.82 -        # Get the class name instead of the fully qualified name.
    1.83 -        full_class_name = str(self.class_file.this_class.get_python_name())
    1.84 -        class_name = full_class_name.split(".")[-1]
    1.85 -        program.load_global(class_name) # Stack: tuple, classref
    1.86 -        program.load_attr("__bases__")  # Stack: tuple, bases
    1.87 -        program.dup_top()               # Stack: tuple, bases, bases
    1.88 -        program.load_global("len")      # Stack: tuple, bases, bases, len
    1.89 -        program.rot_two()               # Stack: tuple, bases, len, bases
    1.90 -        program.call_function(1)        # Stack: tuple, bases, #bases
    1.91 -        program.load_const(0)           # Stack: tuple, bases, #bases, 0
    1.92 -        program.compare_op("==")        # Stack: tuple, bases, result
    1.93 -        program.jump_to_label(1, "no-bases")
    1.94 -        program.pop_top()               # Stack: tuple, bases
    1.95 -        program.load_const(0)           # Stack: tuple, bases, 0
    1.96 -        program.binary_subscr()         # Stack: tuple, bases[0]
    1.97 -        self._invoke(target_name, program)
    1.98 -        program.jump_to_label(None, "done")
    1.99 -
   1.100 -        # No bases found, do no invocation.
   1.101 -        program.start_label("no-bases")
   1.102 -        program.pop_top()               # Stack: tuple, bases
   1.103 -        program.pop_top()               # Stack: tuple
   1.104 -        program.pop_top()               # Stack:
   1.105 -
   1.106 -        program.start_label("done")
   1.107  
   1.108      def invokestatic(self, arguments, program):
   1.109          # NOTE: This implementation does not perform the necessary checks for
   1.110 @@ -1466,14 +1402,15 @@
   1.111          # Get the number of parameters from the descriptor.
   1.112          count = len(target.get_descriptor()[0])
   1.113          # Stack: arg1, arg2, ...
   1.114 -        program.build_tuple(count)      # Stack: tuple
   1.115 +        program.build_tuple(count)          # Stack: tuple
   1.116          # Use the class to provide access to static methods.
   1.117          # Get the class name instead of the fully qualified name.
   1.118 -        # NOTE: Need to find the class that declared the field being accessed.
   1.119 -        full_class_name = str(self.class_file.this_class.get_python_name())
   1.120 -        class_name = full_class_name.split(".")[-1]
   1.121 -        program.load_global(class_name) # Stack: tuple, classref
   1.122 -        self._invoke(target_name, program)
   1.123 +        # NOTE: Do proper resolution of classes,
   1.124 +        full_class_name = target.get_class().get_python_name()
   1.125 +        if full_class_name != "java.lang.Object":
   1.126 +            class_name = full_class_name.split(".")[-1]
   1.127 +            program.load_global(class_name) # Stack: tuple, classref
   1.128 +            self._invoke(target_name, program)
   1.129  
   1.130      def invokevirtual (self, arguments, program):
   1.131          # NOTE: This implementation does not perform the necessary checks for
   1.132 @@ -1578,10 +1515,26 @@
   1.133      lconst_1 = iconst_1
   1.134  
   1.135      def ldc(self, arguments, program):
   1.136 -        program.load_const(self.class_file.constants[arguments[0] - 1].get_value())
   1.137 +        const = self.class_file.constants[arguments[0] - 1]
   1.138 +        if isinstance(const, classfile.StringInfo):
   1.139 +            program.load_global("java")
   1.140 +            program.load_attr("lang")
   1.141 +            program.load_attr("String")
   1.142 +            program.load_const(const.get_value())
   1.143 +            program.call_function(2)
   1.144 +        else:
   1.145 +            program.load_const(const)
   1.146  
   1.147      def ldc_w(self, arguments, program):
   1.148 -        program.load_const(self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1].get_value())
   1.149 +        const = self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1]
   1.150 +        if isinstance(const, classfile.StringInfo):
   1.151 +            program.load_global("java")
   1.152 +            program.load_attr("lang")
   1.153 +            program.load_attr("String")
   1.154 +            program.load_const(const.get_value())
   1.155 +            program.call_function(2)
   1.156 +        else:
   1.157 +            program.load_const(const)
   1.158  
   1.159      ldc2_w = ldc_w
   1.160      ldiv = idiv
   1.161 @@ -1698,11 +1651,10 @@
   1.162          index = (arguments[0] << 8) + arguments[1]
   1.163          target_name = self.class_file.constants[index - 1].get_python_name()
   1.164          # NOTE: Using the string version of the name which may contain incompatible characters.
   1.165 +        program.load_global("object")
   1.166 +        program.load_attr("__new__")
   1.167          program.load_global(str(target_name))
   1.168 -        # NOTE: Unlike Java, we do not provide an object reference. Instead, a
   1.169 -        # NOTE: class reference is provided, and the invokespecial method's
   1.170 -        # NOTE: behaviour is changed.
   1.171 -        #program.call_function(0)
   1.172 +        program.call_function(1)
   1.173  
   1.174      def newarray(self, arguments, program):
   1.175          # NOTE: Does not raise NegativeArraySizeException.
   1.176 @@ -1835,17 +1787,19 @@
   1.177          translator.process(method, writer)
   1.178          return translator, writer
   1.179  
   1.180 -    def make_method(self, method_name, methods, global_names, namespace):
   1.181 +    def make_method(self, real_method_name, methods, global_names, namespace):
   1.182  
   1.183          """
   1.184 -        Make a dispatcher method with the given 'method_name', providing
   1.185 +        Make a dispatcher method with the given 'real_method_name', providing
   1.186          dispatch to the supplied type-sensitive 'methods', accessing the given
   1.187          'global_names' where necessary, and storing the new method in the
   1.188          'namespace' provided.
   1.189          """
   1.190  
   1.191 -        if method_name == "<init>":
   1.192 +        if real_method_name == "<init>":
   1.193              method_name = "__init__"
   1.194 +        else:
   1.195 +            method_name = real_method_name
   1.196  
   1.197          # Where only one method exists, just make an alias.
   1.198  
   1.199 @@ -1854,19 +1808,33 @@
   1.200              namespace[method_name] = fn
   1.201              return
   1.202  
   1.203 -        # Find the maximum number of parameters involved.
   1.204 -        #maximum = max([len(method.get_descriptor()[0]) for method in methods])
   1.205 +        # Write a simple bytecode dispatching mechanism.
   1.206  
   1.207          program = BytecodeWriter()
   1.208  
   1.209 +        # Remember whether any of the methods are static.
   1.210 +        # NOTE: This should be an all or nothing situation.
   1.211 +
   1.212 +        method_is_static = 0
   1.213 +
   1.214          # NOTE: The code below should use dictionary-based dispatch for better performance.
   1.215  
   1.216 -        program.load_fast(1)                        # Stack: arguments
   1.217          for method, fn in methods:
   1.218 +            method_is_static = real_method_name != "<init>" and method_is_static or classfile.has_flags(method.access_flags, [classfile.STATIC])
   1.219 +
   1.220 +            if method_is_static:
   1.221 +                program.load_fast(0)                # Stack: arguments
   1.222 +            else:
   1.223 +                program.load_fast(1)                # Stack: arguments
   1.224 +
   1.225              program.setup_loop()
   1.226 -            program.dup_top()                       # Stack: arguments, arguments
   1.227 -            program.load_const(1)                   # Stack: arguments, arguments, 1
   1.228 -            program.store_fast(2)                   # Stack: arguments, arguments (found = 1)
   1.229 +            program.load_const(1)                   # Stack: arguments, 1
   1.230 +
   1.231 +            if method_is_static:
   1.232 +                program.store_fast(1)               # Stack: arguments (found = 1)
   1.233 +            else:
   1.234 +                program.store_fast(2)               # Stack: arguments (found = 1)
   1.235 +
   1.236              # Emit a list of parameter types.
   1.237              descriptor_types = method.get_descriptor()[0]
   1.238              for descriptor_type in descriptor_types:
   1.239 @@ -1875,77 +1843,104 @@
   1.240                  if python_type == "instance":
   1.241                      # NOTE: This will need extending.
   1.242                      python_type = object_type
   1.243 -                program.load_global(python_type)    # Stack: arguments, arguments, type, ...
   1.244 +                program.load_global(python_type)    # Stack: arguments, type, ...
   1.245              program.build_list(len(descriptor_types))
   1.246 -                                                    # Stack: arguments, arguments, types
   1.247 +                                                    # Stack: arguments, types
   1.248              # Make a map of arguments and types.
   1.249 -            program.load_const(None)                # Stack: arguments, arguments, types, None
   1.250 -            program.rot_three()                     # Stack: arguments, None, arguments, types
   1.251 -            program.build_tuple(3)                  # Stack: arguments, tuple
   1.252 -            program.load_global("map")              # Stack: arguments, tuple, map
   1.253 -            program.rot_two()                       # Stack: arguments, map, tuple
   1.254 -            program.call_function_var(0)            # Stack: arguments, list (mapping arguments to types)
   1.255 +            program.load_const(None)                # Stack: arguments, types, None
   1.256 +            program.rot_three()                     # Stack: None, arguments, types
   1.257 +            program.build_tuple(3)                  # Stack: tuple
   1.258 +            program.load_global("map")              # Stack: tuple, map
   1.259 +            program.rot_two()                       # Stack: map, tuple
   1.260 +            program.call_function_var(0)            # Stack: list (mapping arguments to types)
   1.261              # Loop over each pair.
   1.262 -            program.get_iter()                      # Stack: arguments, iter
   1.263 -            program.for_iter()                      # Stack: arguments, iter, (argument, type)
   1.264 -            program.unpack_sequence(2)              # Stack: arguments, iter, type, argument
   1.265 -            program.dup_top()                       # Stack: arguments, iter, type, argument, argument
   1.266 -            program.load_const(None)                # Stack: arguments, iter, type, argument, argument, None
   1.267 -            program.compare_op("is")                # Stack: arguments, iter, type, argument, result
   1.268 +            program.get_iter()                      # Stack: iter
   1.269 +            program.for_iter()                      # Stack: iter, (argument, type)
   1.270 +            program.unpack_sequence(2)              # Stack: iter, type, argument
   1.271 +            program.dup_top()                       # Stack: iter, type, argument, argument
   1.272 +            program.load_const(None)                # Stack: iter, type, argument, argument, None
   1.273 +            program.compare_op("is")                # Stack: iter, type, argument, result
   1.274              # Missing argument?
   1.275              program.jump_to_label(0, "present")
   1.276 -            program.pop_top()                       # Stack: arguments, iter, type, argument
   1.277 -            program.pop_top()                       # Stack: arguments, iter, type
   1.278 -            program.pop_top()                       # Stack: arguments, iter
   1.279 -            program.load_const(0)                   # Stack: arguments, iter, 0
   1.280 -            program.store_fast(2)                   # Stack: arguments, iter (found = 0)
   1.281 +            program.pop_top()                       # Stack: iter, type, argument
   1.282 +            program.pop_top()                       # Stack: iter, type
   1.283 +            program.pop_top()                       # Stack: iter
   1.284 +            program.load_const(0)                   # Stack: iter, 0
   1.285 +
   1.286 +            if method_is_static:
   1.287 +                program.store_fast(1)               # Stack: iter (found = 0)
   1.288 +            else:
   1.289 +                program.store_fast(2)               # Stack: iter (found = 0)
   1.290 +
   1.291              program.break_loop()
   1.292              # Argument was present.
   1.293              program.start_label("present")
   1.294 -            program.pop_top()                       # Stack: arguments, iter, type, argument
   1.295 -            program.rot_two()                       # Stack: arguments, iter, argument, type
   1.296 -            program.dup_top()                       # Stack: arguments, iter, argument, type, type
   1.297 -            program.load_const(None)                # Stack: arguments, iter, argument, type, type, None
   1.298 -            program.compare_op("is")                # Stack: arguments, iter, argument, type, result
   1.299 +            program.pop_top()                       # Stack: iter, type, argument
   1.300 +            program.rot_two()                       # Stack: iter, argument, type
   1.301 +            program.dup_top()                       # Stack: iter, argument, type, type
   1.302 +            program.load_const(None)                # Stack: iter, argument, type, type, None
   1.303 +            program.compare_op("is")                # Stack: iter, argument, type, result
   1.304              # Missing parameter type?
   1.305              program.jump_to_label(0, "present")
   1.306 -            program.pop_top()                       # Stack: arguments, iter, argument, type
   1.307 -            program.pop_top()                       # Stack: arguments, iter, argument
   1.308 -            program.pop_top()                       # Stack: arguments, iter
   1.309 -            program.load_const(0)                   # Stack: arguments, iter, 0
   1.310 -            program.store_fast(2)                   # Stack: arguments, iter (found = 0)
   1.311 +            program.pop_top()                       # Stack: iter, argument, type
   1.312 +            program.pop_top()                       # Stack: iter, argument
   1.313 +            program.pop_top()                       # Stack: iter
   1.314 +            program.load_const(0)                   # Stack: iter, 0
   1.315 +
   1.316 +            if method_is_static:
   1.317 +                program.store_fast(1)               # Stack: iter (found = 0)
   1.318 +            else:
   1.319 +                program.store_fast(2)               # Stack: iter (found = 0)
   1.320 +
   1.321              program.break_loop()
   1.322              # Parameter was present.
   1.323              program.start_label("present")
   1.324 -            program.pop_top()                       # Stack: arguments, iter, argument, type
   1.325 -            program.build_tuple(2)                  # Stack: arguments, iter, (argument, type)
   1.326 -            program.load_global("isinstance")       # Stack: arguments, iter, (argument, type), isinstance
   1.327 -            program.rot_two()                       # Stack: arguments, iter, isinstance, (argument, type)
   1.328 -            program.call_function_var(0)            # Stack: arguments, iter, result
   1.329 +            program.pop_top()                       # Stack: iter, argument, type
   1.330 +            program.build_tuple(2)                  # Stack: iter, (argument, type)
   1.331 +            program.load_global("isinstance")       # Stack: iter, (argument, type), isinstance
   1.332 +            program.rot_two()                       # Stack: iter, isinstance, (argument, type)
   1.333 +            program.call_function_var(0)            # Stack: iter, result
   1.334              program.jump_to_label(1, "match")
   1.335 -            program.pop_top()                       # Stack: arguments, iter
   1.336 -            program.load_const(0)                   # Stack: arguments, iter, 0
   1.337 -            program.store_fast(2)                   # Stack: arguments, iter (found = 0)
   1.338 +            program.pop_top()                       # Stack: iter
   1.339 +            program.load_const(0)                   # Stack: iter, 0
   1.340 +
   1.341 +            if method_is_static:
   1.342 +                program.store_fast(1)               # Stack: iter (found = 0)
   1.343 +            else:
   1.344 +                program.store_fast(2)               # Stack: iter (found = 0)
   1.345 +
   1.346              program.break_loop()
   1.347              # Argument type and parameter type matched.
   1.348              program.start_label("match")
   1.349 -            program.pop_top()                       # Stack: arguments, iter
   1.350 -            program.end_loop()                      # Stack: arguments
   1.351 +            program.pop_top()                       # Stack: iter
   1.352 +            program.end_loop()                      # Stack:
   1.353              # If all the parameters matched, call the method.
   1.354 -            program.load_fast(2)                    # Stack: arguments, match
   1.355 +
   1.356 +            if method_is_static:
   1.357 +                program.load_fast(1)                # Stack: match
   1.358 +            else:
   1.359 +                program.load_fast(2)                # Stack: match
   1.360 +
   1.361              program.jump_to_label(0, "failed")
   1.362              # All the parameters matched.
   1.363 -            program.pop_top()                       # Stack: arguments
   1.364 -            program.dup_top()                       # Stack: arguments, arguments
   1.365 -            program.load_fast(0)                    # Stack: arguments, arguments, self
   1.366 +            program.pop_top()                       # Stack:
   1.367 +
   1.368 +            if method_is_static:
   1.369 +                program.load_fast(0)                # Stack: arguments
   1.370 +                program.load_global(str(self.class_file.this_class.get_python_name()))
   1.371 +                                                    # Stack: arguments, class
   1.372 +            else:
   1.373 +                program.load_fast(1)                # Stack: arguments
   1.374 +                program.load_fast(0)                # Stack: arguments, self
   1.375 +
   1.376              program.load_attr(str(method.get_python_name()))
   1.377 -                                                    # Stack: arguments, arguments, method
   1.378 -            program.rot_two()                       # Stack: arguments, method, arguments
   1.379 -            program.call_function_var(0)            # Stack: arguments, result
   1.380 +                                                    # Stack: arguments, method
   1.381 +            program.rot_two()                       # Stack: method, arguments
   1.382 +            program.call_function_var(0)            # Stack: result
   1.383              program.return_value()
   1.384              # Try the next method if arguments or parameters were missing or incorrect.
   1.385              program.start_label("failed")
   1.386 -            program.pop_top()                       # Stack: arguments
   1.387 +            program.pop_top()                       # Stack:
   1.388  
   1.389          # Raise an exception if nothing matched.
   1.390          # NOTE: Improve this.
   1.391 @@ -1959,11 +1954,20 @@
   1.392          # NOTE: One actual parameter, flags as 71 apparently means that a list
   1.393          # NOTE: parameter is used in a method.
   1.394  
   1.395 +        if method_is_static:
   1.396 +            nargs = 0
   1.397 +        else:
   1.398 +            nargs = 1
   1.399          nlocals = program.max_locals + 1
   1.400 -        code = new.code(1, nlocals, program.max_stack_depth, 71, program.get_output(),
   1.401 -            tuple(program.get_constants()), tuple(program.get_names()), tuple(self.make_varnames(nlocals)),
   1.402 +
   1.403 +        code = new.code(nargs, nlocals, program.max_stack_depth, 71, program.get_output(),
   1.404 +            tuple(program.get_constants()), tuple(program.get_names()), tuple(self.make_varnames(nlocals, method_is_static)),
   1.405              self.filename, method_name, 0, "")
   1.406          fn = new.function(code, global_names)
   1.407 +
   1.408 +        if method_is_static:
   1.409 +            fn = staticmethod(fn)
   1.410 +
   1.411          namespace[method_name] = fn
   1.412  
   1.413      def process(self, global_names):
   1.414 @@ -1986,39 +1990,40 @@
   1.415          real_methods = {}
   1.416          for method in self.class_file.methods:
   1.417              real_method_name = str(method.get_name())
   1.418 +            method_name = str(method.get_python_name())
   1.419 +
   1.420              t, w = self.translate_method(method)
   1.421  
   1.422 -            # Fix up special class initialisation methods.
   1.423 +            # Fix up special class initialisation methods and static methods.
   1.424  
   1.425 -            if real_method_name == "<clinit>":
   1.426 -                flags = 3
   1.427 +            method_is_static = real_method_name != "<init>" and classfile.has_flags(method.access_flags, [classfile.STATIC])
   1.428 +            if method_is_static:
   1.429 +                nargs = len(method.get_descriptor()[0])
   1.430              else:
   1.431 -                flags = 67
   1.432 +                nargs = len(method.get_descriptor()[0]) + 1
   1.433              nlocals = w.max_locals + 1
   1.434 -            nargs = len(method.get_descriptor()[0]) + 1
   1.435 -
   1.436 -            method_name = str(method.get_python_name())
   1.437 +            flags = 67
   1.438  
   1.439              # NOTE: Add line number table later.
   1.440  
   1.441              code = new.code(nargs, nlocals, w.max_stack_depth, flags, w.get_output(), tuple(w.get_constants()), tuple(w.get_names()),
   1.442 -                tuple(self.make_varnames(nlocals)), self.filename, method_name, 0, "")
   1.443 +                tuple(self.make_varnames(nlocals, method_is_static)), self.filename, method_name, 0, "")
   1.444  
   1.445              # NOTE: May need more globals.
   1.446  
   1.447              fn = new.function(code, global_names)
   1.448  
   1.449 +            # Fix up special class initialisation methods and static methods.
   1.450 +
   1.451 +            if method_is_static:
   1.452 +                fn = staticmethod(fn)
   1.453 +
   1.454              # Remember the real method name and the corresponding methods produced.
   1.455  
   1.456              if not real_methods.has_key(real_method_name):
   1.457                  real_methods[real_method_name] = []
   1.458              real_methods[real_method_name].append((method, fn))
   1.459  
   1.460 -            # Fix up special class initialisation methods.
   1.461 -
   1.462 -            if real_method_name == "<clinit>":
   1.463 -                fn = classmethod(fn)
   1.464 -
   1.465              # Add the method to the class's namespace.
   1.466  
   1.467              namespace[method_name] = fn
   1.468 @@ -2053,7 +2058,7 @@
   1.469  
   1.470          original_name = str(self.class_file.super_class.get_name())
   1.471          if original_name in ("java/lang/Object", "java/lang/Exception"):
   1.472 -            return ()
   1.473 +            return (object,)
   1.474          else:
   1.475              full_this_class_name = str(self.class_file.this_class.get_python_name())
   1.476              this_class_name_parts = full_this_class_name.split(".")
   1.477 @@ -2074,15 +2079,21 @@
   1.478                      obj = getattr(obj, super_class_name_part)
   1.479              return (obj,)
   1.480  
   1.481 -    def make_varnames(self, nlocals):
   1.482 +    def make_varnames(self, nlocals, method_is_static=0):
   1.483  
   1.484          """
   1.485          A utility method which invents variable names for the given number -
   1.486          'nlocals' - of local variables in a method. Returns a list of such
   1.487          variable names.
   1.488 +
   1.489 +        If the optional 'method_is_static' is set to true, do not use "self" as
   1.490 +        the first argument name.
   1.491          """
   1.492  
   1.493 -        l = ["self"]
   1.494 +        if method_is_static:
   1.495 +            l = ["cls"]
   1.496 +        else:
   1.497 +            l = ["self"]
   1.498          for i in range(1, nlocals):
   1.499              l.append("_l%s" % i)
   1.500          return l[:nlocals]