javaclass

Change of bytecode.py

85:85e3410a7de9
bytecode.py
     1.1 --- a/bytecode.py	Thu Dec 09 20:51:18 2004 +0100
     1.2 +++ b/bytecode.py	Fri Dec 10 01:04:59 2004 +0100
     1.3 @@ -284,14 +284,14 @@
     1.4          # NOTE: Using 3 as the assumed length of the SETUP_* instruction.
     1.5          self._rewrite_value(current_exception_start + 1, target - current_exception_start - 3)
     1.6  
     1.7 -    def start_handler(self, exc_name):
     1.8 +    def start_handler(self, exc_name, class_file):
     1.9  
    1.10          # Where handlers are begun, produce bytecode to test the type of
    1.11          # the exception.
    1.12          # NOTE: Since RAISE_VARARGS and END_FINALLY are not really documented,
    1.13          # NOTE: we store the top of the stack and use it later to trigger the
    1.14          # NOTE: magic processes when re-raising.
    1.15 -        self.use_external_name(exc_name)
    1.16 +        self.use_external_name(str(exc_name))
    1.17  
    1.18          self.rot_two()                      # Stack: raised-exception, exception
    1.19          self.dup_top()                      # Stack: raised-exception, exception, exception
    1.20 @@ -304,7 +304,8 @@
    1.21          self.load_attr("args")              # Stack: raised-exception, exception, args
    1.22          self.load_const(0)                  # Stack: raised-exception, exception, args, 0
    1.23          self.binary_subscr()                # Stack: raised-exception, exception, exception-object
    1.24 -        self.load_global(str(exc_name))     # Stack: raised-exception, exception, exception-object, handled-exception
    1.25 +        load_class_name(class_file, str(exc_name), self)
    1.26 +                                            # Stack: raised-exception, exception, exception-object, handled-exception
    1.27          self.load_global("isinstance")      # Stack: raised-exception, exception, exception-object, handled-exception, isinstance
    1.28          self.rot_three()                    # Stack: raised-exception, exception, isinstance, exception-object, handled-exception
    1.29          self.call_function(2)               # Stack: raised-exception, exception, result
    1.30 @@ -632,6 +633,21 @@
    1.31  def signed4(value):
    1.32      return signed(value, 0x80000000)
    1.33  
    1.34 +def load_class_name(class_file, full_class_name, program):
    1.35 +    this_class_name = str(class_file.this_class.get_python_name())
    1.36 +    this_class_parts = this_class_name.split(".")
    1.37 +    class_parts = full_class_name.split(".")
    1.38 +
    1.39 +    # Only use the full path if different from this class's path.
    1.40 +
    1.41 +    if class_parts[:-1] != this_class_parts[:-1]:
    1.42 +        program.use_external_name(full_class_name)
    1.43 +        program.load_global(class_parts[0])
    1.44 +        for class_part in class_parts[1:]:
    1.45 +            program.load_attr(class_part)   # Stack: classref
    1.46 +    else:
    1.47 +        program.load_global(class_parts[-1])
    1.48 +
    1.49  # Bytecode conversion.
    1.50  
    1.51  class BytecodeReader:
    1.52 @@ -736,7 +752,7 @@
    1.53                  if exception.catch_type == 0:
    1.54                      self.in_finally = 1
    1.55                  else:
    1.56 -                    program.start_handler(self.class_file.constants[exception.catch_type - 1].get_python_name())
    1.57 +                    program.start_handler(self.class_file.constants[exception.catch_type - 1].get_python_name(), self.class_file)
    1.58  
    1.59              # Process the bytecode at the current position.
    1.60  
    1.61 @@ -1034,7 +1050,7 @@
    1.62          print "(setup_finally %s)" % target
    1.63      def end_exception(self):
    1.64          print "(end_exception)"
    1.65 -    def start_handler(self, exc_name):
    1.66 +    def start_handler(self, exc_name, class_file):
    1.67          print "(start_handler %s)" % exc_name
    1.68      def pop_block(self):
    1.69          print "(pop_block)"
    1.70 @@ -1043,17 +1059,6 @@
    1.71  
    1.72      "A Java bytecode translator which uses a Python bytecode writer."
    1.73  
    1.74 -    def _load_class_name(self, full_class_name, program):
    1.75 -        this_class_name = str(self.class_file.this_class.get_python_name())
    1.76 -        class_parts = full_class_name.split(".")
    1.77 -        if full_class_name != this_class_name:
    1.78 -            program.use_external_name(full_class_name)
    1.79 -            program.load_global(class_parts[0])
    1.80 -            for class_part in class_parts[1:]:
    1.81 -                program.load_attr(class_part)   # Stack: classref
    1.82 -        else:
    1.83 -            program.load_global(class_parts[-1])
    1.84 -
    1.85      def aaload(self, arguments, program):
    1.86          # NOTE: No type checking performed.
    1.87          program.binary_subscr()
    1.88 @@ -1158,17 +1163,30 @@
    1.89          index = (arguments[0] << 8) + arguments[1]
    1.90          target_name = self.class_file.constants[index - 1].get_python_name()
    1.91          program.use_external_name(target_name)
    1.92 -
    1.93 -        # NOTE: Using the string version of the name which may contain incompatible characters.
    1.94 -        target_components = str(target_name).split("/")
    1.95 -
    1.96 +        program.dup_top()                   # Stack: objectref, objectref
    1.97 +        program.load_const(None)            # Stack: objectref, objectref, None
    1.98 +        program.compare_op("is")            # Stack: objectref, result
    1.99 +        program.jump_to_label(1, "next")
   1.100 +        program.pop_top()                   # Stack: objectref
   1.101          program.dup_top()                   # Stack: objectref, objectref
   1.102          program.load_global("isinstance")   # Stack: objectref, objectref, isinstance
   1.103          program.rot_two()                   # Stack: objectref, isinstance, objectref
   1.104 -        program.load_global(target_components[0])
   1.105 -        for target_component in target_components[1:]:
   1.106 -            program.load_attr(target_component)
   1.107 -        program.call_function(2)            # Stack: objectref
   1.108 +        load_class_name(self.class_file, target_name, program)
   1.109 +        program.call_function(2)            # Stack: objectref, result
   1.110 +        program.jump_to_label(1, "next")
   1.111 +        program.pop_top()                   # Stack: objectref
   1.112 +        program.pop_top()                   # Stack:
   1.113 +        program.use_external_name("java.lang.ClassCastException")
   1.114 +        load_class_name(self.class_file, "java.lang.ClassCastException", program)
   1.115 +        program.call_function(0)            # Stack: exception
   1.116 +        # Wrap the exception in a Python exception.
   1.117 +        program.load_global("Exception")    # Stack: exception, Exception
   1.118 +        program.rot_two()                   # Stack: Exception, exception
   1.119 +        program.call_function(1)            # Stack: exception
   1.120 +        program.raise_varargs(1)
   1.121 +        # NOTE: This seems to put another object on the stack.
   1.122 +        program.start_label("next")
   1.123 +        program.pop_top()                   # Stack: objectref
   1.124  
   1.125      def d2f(self, arguments, program):
   1.126          pass
   1.127 @@ -1302,7 +1320,8 @@
   1.128          # Get the class name instead of the fully qualified name.
   1.129  
   1.130          full_class_name = target.get_class().get_python_name()
   1.131 -        self._load_class_name(full_class_name, program)
   1.132 +        program.use_external_name(full_class_name)
   1.133 +        load_class_name(self.class_file, full_class_name, program)
   1.134          # NOTE: Using the string version of the name which may contain incompatible characters.
   1.135          program.load_attr(str(target_name))
   1.136  
   1.137 @@ -1468,15 +1487,9 @@
   1.138          index = (arguments[0] << 8) + arguments[1]
   1.139          target_name = self.class_file.constants[index - 1].get_python_name()
   1.140          program.use_external_name(target_name)
   1.141 -
   1.142 -        # NOTE: Using the string version of the name which may contain incompatible characters.
   1.143 -        target_components = str(target_name).split("/")
   1.144 -
   1.145          program.load_global("isinstance")   # Stack: objectref, isinstance
   1.146          program.rot_two()                   # Stack: isinstance, objectref
   1.147 -        program.load_global(target_components[0])
   1.148 -        for target_component in target_components[1:]:
   1.149 -            program.load_attr(target_component)
   1.150 +        load_class_name(self.class_file, target_name, program)
   1.151          program.call_function(2)            # Stack: result
   1.152  
   1.153      def _invoke(self, target_name, program):
   1.154 @@ -1522,7 +1535,8 @@
   1.155  
   1.156          full_class_name = target.get_class().get_python_name()
   1.157          if full_class_name not in ("java.lang.Object", "java.lang.Exception"):
   1.158 -            self._load_class_name(full_class_name, program)
   1.159 +            program.use_external_name(full_class_name)
   1.160 +            load_class_name(self.class_file, full_class_name, program)
   1.161              self._invoke(target_name, program)
   1.162  
   1.163          # Remove Python None return value.
   1.164 @@ -1551,7 +1565,8 @@
   1.165  
   1.166          full_class_name = target.get_class().get_python_name()
   1.167          if full_class_name not in ("java.lang.Object", "java.lang.Exception"):
   1.168 -            self._load_class_name(full_class_name, program)
   1.169 +            program.use_external_name(full_class_name)
   1.170 +            load_class_name(self.class_file, full_class_name, program)
   1.171              self._invoke(target_name, program)
   1.172  
   1.173      def invokevirtual (self, arguments, program):
   1.174 @@ -1666,7 +1681,7 @@
   1.175              program.load_const(const.get_value())
   1.176              program.call_function(1)
   1.177          else:
   1.178 -            program.load_const(const)
   1.179 +            program.load_const(const.get_value())
   1.180  
   1.181      def ldc_w(self, arguments, program):
   1.182          const = self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1]
   1.183 @@ -1678,7 +1693,7 @@
   1.184              program.load_const(const.get_value())
   1.185              program.call_function(1)
   1.186          else:
   1.187 -            program.load_const(const)
   1.188 +            program.load_const(const.get_value())
   1.189  
   1.190      ldc2_w = ldc_w
   1.191      ldiv = idiv
   1.192 @@ -1800,7 +1815,7 @@
   1.193          # NOTE: Using the string version of the name which may contain incompatible characters.
   1.194          program.load_global("object")
   1.195          program.load_attr("__new__")
   1.196 -        self._load_class_name(target_name, program)
   1.197 +        load_class_name(self.class_file, target_name, program)
   1.198          program.call_function(1)
   1.199  
   1.200      def newarray(self, arguments, program):
   1.201 @@ -1831,7 +1846,8 @@
   1.202          # Get the class name instead of the fully qualified name.
   1.203  
   1.204          full_class_name = target.get_class().get_python_name()
   1.205 -        self._load_class_name(full_class_name, program)
   1.206 +        program.use_external_name(full_class_name)
   1.207 +        load_class_name(self.class_file, full_class_name, program)
   1.208          # NOTE: Using the string version of the name which may contain incompatible characters.
   1.209          program.store_attr(str(target_name))
   1.210