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