PageRenderTime 51ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/translator/jvm/typesystem.py

https://bitbucket.org/pypy/pypy/
Python | 991 lines | 951 code | 4 blank | 36 comment | 8 complexity | 5e0333b65a82c24fbc71008c967fdcbb MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Defines the basic structures which are used to represent JVM abstraction,
  3. such as Java types, fields, methods and opcodes.
  4. The structures in this file generally two different, but related,
  5. roles. First, they describe a JVM abstraction. For example, jObject
  6. describes some of the properties of the built-in class
  7. java.lang.Object. Second, they can represent the concrete realization
  8. of an OOTYPE construct. For example, JvmType instances are used to
  9. represent the translated class which will be generated for some OOTYPE
  10. class.
  11. This file itself is intended to be imported from a wide variety of
  12. locations, and thus generally restricts itself to classes and global
  13. variables that describe intrinsic parts of the JVM. For example,
  14. there are objects representing different opcodes, type definitions for
  15. built-in types like java.lang.Object and java.lang.System, and
  16. method/field declarations for well-known methods and fields on those
  17. types.
  18. Other files extend this set with objects that represent the JVM
  19. realization of some OOTYPE construct. For example, the module
  20. builtin.py describes the JVM types that are used to define the
  21. built-in OOTYPE types, such as lists or dictionaries. The module
  22. node.py contains code for representing user-defined classes.
  23. """
  24. from pypy.rpython.lltypesystem import lltype, llmemory
  25. from pypy.rpython.ootypesystem import ootype
  26. from pypy.translator.jvm.option import getoption
  27. from pypy.translator.jvm.log import log
  28. # ___________________________________________________________________________
  29. # Type Descriptors
  30. #
  31. # Internal representations of types for the JVM. Generally speaking,
  32. # only the generator code should deal with these and even it tries to
  33. # avoid them except write before dumping to the output file.
  34. class JvmTypeDescriptor(str):
  35. """
  36. An internal class representing JVM type descriptors, which are
  37. essentially Java's short hand for types. This is the lowest level
  38. of our representation for types and are mainly used when defining
  39. the types of fields or arguments to methods. The grammar for type
  40. descriptors can be read about here:
  41. http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
  42. We use this class also to represent method descriptors, which define
  43. a set of argument and return types.
  44. """
  45. def is_scalar(self):
  46. return self[0] != 'L' and self[0] != '['
  47. def is_reference(self):
  48. return not self.is_scalar()
  49. def is_array(self):
  50. return self[0] == '['
  51. def is_method(self):
  52. return self[0] == '('
  53. def class_name(self):
  54. """ Converts a descriptor like Ljava/lang/Object; to
  55. full class name java.lang.Object """
  56. return self.int_class_name().replace('/','.')
  57. def int_class_name(self):
  58. """ Converts a descriptor like Ljava/lang/Object; to
  59. internal class name java/lang/Object """
  60. if self[0] == 'L' and self[-1] == ';':
  61. return self[1:-1]
  62. else:
  63. assert self.startswith('[')
  64. return self
  65. def type_width(self):
  66. """ Returns number of JVM words this type takes up. JVM words
  67. are a theoretically abstract quantity that basically
  68. represents 32 bits; so most types are 1, but longs and doubles
  69. are 2. """
  70. if self[0] == 'J' or self[0] == 'D':
  71. return 2
  72. return 1
  73. # JVM type functions
  74. def desc_for_array_of(jdescr):
  75. """ Returns a JvmType representing an array of 'jtype', which must be
  76. another JvmType """
  77. assert isinstance(jdescr, JvmTypeDescriptor)
  78. return JvmTypeDescriptor('['+jdescr)
  79. def desc_for_class(classnm):
  80. """ Returns a JvmType representing a particular class 'classnm', which
  81. should be a fully qualified java class name (i.e., 'java.lang.String') """
  82. return JvmTypeDescriptor('L%s;' % classnm.replace('.','/'))
  83. def desc_for_method(argtypes, rettype):
  84. """ A Java method has a descriptor, which is a string specified
  85. its argument and return types. This function converts a list of
  86. argument types (JvmTypes) and the return type (also a JvmType),
  87. into one of these descriptor strings. """
  88. return JvmTypeDescriptor("(%s)%s" % ("".join(argtypes), rettype))
  89. # ______________________________________________________________________
  90. # Basic JVM Types
  91. #
  92. # As described above, some of these define well-known types in the JVM
  93. # or standard Java library. In addition, there are subtypes of
  94. # JvmType which represent the translated version of some RPython
  95. # class, such as a list, dictionary, or user-defined class. Those
  96. # subtypes are generally defined in other modules, as they have
  97. # dependencies that would cause circular imports.
  98. class JvmType(object):
  99. """
  100. The JvmType interface defines the interface for type objects
  101. that we return in the database in various places.
  102. """
  103. def __init__(self, descriptor):
  104. """ 'descriptor' should be a jvm.generator.JvmTypeDescriptor object
  105. for this type """
  106. self.descriptor = descriptor # public
  107. self.name = None # public, string like "java.lang.Object"
  108. # (None for scalars and arrays)
  109. def lookup_field(self, fieldnm):
  110. """ Returns a Field or Property object that represents the
  111. field named 'fieldnm', or raises KeyError if no such field
  112. exists. 'fieldnm' generally represents an OOTYPE field, and
  113. thus this method is generally not implemenented by the JvmType
  114. classes that just represent native Java classes, even if they
  115. have fields. Instead, such fields are described as global
  116. Field constants, either in this file or elsewhere. """
  117. raise NotImplementedException
  118. def lookup_method(self, methodnm):
  119. """ Returns a BaseMethod object that represents the method
  120. named 'methodnm', or raises KeyError if no such field exists.
  121. 'methodnm' represents an OOTYPE method, and thus this method
  122. is generally not implemenented by the JvmType classes that
  123. just represent native Java classes, even if they have methods.
  124. Instead, such methods are described as global Method constants
  125. in this file, either in this file or elsewhere. """
  126. raise NotImplementedException
  127. def is_generated(self):
  128. """ Indicates whether the source for this type is generated by
  129. pypy. """
  130. return False
  131. def __repr__(self):
  132. return "%s<%s>" % (self.__class__.__name__, self.descriptor)
  133. class JvmClassType(JvmType):
  134. """
  135. Base class used for all class instances. Kind of an abstract class;
  136. instances of this class do not support field or method lookup and
  137. only work to obtain the descriptor. We use it on occasion for classes
  138. like java.lang.Object etc.
  139. """
  140. def __init__(self, classnm, throwable=False):
  141. JvmType.__init__(self, desc_for_class(classnm))
  142. self.name = classnm # public; String, like 'java.lang.Object'
  143. self.throwable = throwable # public; boolean
  144. def lookup_field(self, fieldnm):
  145. raise KeyError(fieldnm) # we treat as opaque type
  146. def lookup_method(self, methodnm):
  147. raise KeyError(fieldnm) # we treat as opaque type
  148. class JvmGeneratedClassType(JvmClassType):
  149. """ Abstract class extended by the classes in node.py that represent
  150. generated classes """
  151. def is_generated(self):
  152. return True
  153. class JvmInterfaceType(JvmClassType):
  154. pass
  155. class JvmGeneratedInterfaceType(JvmInterfaceType):
  156. """ Abstract class extended by the classes in node.py that represent
  157. generated interfaces """
  158. def is_generated(self):
  159. return True
  160. jIntegerClass = JvmClassType('java.lang.Integer')
  161. jLongClass = JvmClassType('java.lang.Long')
  162. jShortClass = JvmClassType('java.lang.Short')
  163. jDoubleClass = JvmClassType('java.lang.Double')
  164. jByteClass = JvmClassType('java.lang.Byte')
  165. jCharClass = JvmClassType('java.lang.Character')
  166. jBoolClass = JvmClassType('java.lang.Boolean')
  167. jThrowable = JvmClassType('java.lang.Throwable', throwable=True)
  168. jPyPyThrowable = JvmClassType('pypy.PyPyThrowable', throwable=True)
  169. jObject = JvmClassType('java.lang.Object')
  170. jString = JvmClassType('java.lang.String')
  171. jCharSequence = JvmClassType('java.lang.CharSequence')
  172. jArrays = JvmClassType('java.util.Arrays')
  173. jMap = JvmInterfaceType('java.util.Map')
  174. jHashMap = JvmClassType('java.util.HashMap')
  175. jIterator = JvmClassType('java.util.Iterator')
  176. jClass = JvmClassType('java.lang.Class')
  177. jStringBuilder = JvmClassType('java.lang.StringBuilder')
  178. jSystem = JvmClassType('java.lang.System')
  179. jPrintStream = JvmClassType('java.io.PrintStream')
  180. jMath = JvmClassType('java.lang.Math')
  181. jList = JvmInterfaceType('java.util.List')
  182. jArrayList = JvmClassType('java.util.ArrayList')
  183. jPyPy = JvmClassType('pypy.PyPy')
  184. jPyPyExcWrap = JvmClassType('pypy.ExceptionWrapper')
  185. jPyPyDictItemsIterator = JvmClassType('pypy.DictItemsIterator')
  186. jPyPyInterlink = JvmInterfaceType('pypy.Interlink')
  187. jPyPyCustomDict = JvmClassType('pypy.CustomDict')
  188. jPyPyStatResult = JvmClassType('pypy.StatResult')
  189. jPyPyWeakRef = JvmClassType('pypy.PyPyWeakRef')
  190. jll_os = JvmClassType('pypy.ll_os')
  191. jPyPyRecordSignedSigned = JvmClassType('pypy.RecordSignedSigned')
  192. jPyPyRecordStringString = JvmClassType('pypy.RecordStringString')
  193. jPyPyRecordFloatSigned = JvmClassType('pypy.RecordFloatSigned')
  194. jPyPyRecordFloatFloat = JvmClassType('pypy.RecordFloatFloat')
  195. jPyPyAbstractMethodException = JvmClassType('pypy.AbstractMethodException')
  196. jStackOverflowError = JvmClassType('java.lang.StackOverflowError', throwable=True)
  197. jOutOfMemoryError = JvmClassType('java.lang.OutOfMemoryError', throwable=True)
  198. jArithmeticException = JvmClassType('java.lang.ArithmeticException', throwable=True)
  199. class JvmScalarType(JvmType):
  200. """
  201. Subclass used for all scalar type instances.
  202. """
  203. def __init__(self, descrstr, boxtype, unboxmethod):
  204. JvmType.__init__(self, JvmTypeDescriptor(descrstr))
  205. self.box_type = boxtype
  206. self.unbox_method = unboxmethod
  207. def lookup_field(self, fieldnm):
  208. raise KeyError(fieldnm) # Scalar objects have no fields
  209. def lookup_method(self, methodnm):
  210. raise KeyError(methodnm) # Scalar objects have no methods
  211. jVoid = JvmScalarType('V', None, None)
  212. jInt = JvmScalarType('I', jIntegerClass, 'intValue')
  213. jLong = JvmScalarType('J', jLongClass, 'longValue')
  214. jBool = JvmScalarType('Z', jBoolClass, 'booleanValue')
  215. jDouble = JvmScalarType('D', jDoubleClass, 'doubleValue')
  216. jByte = JvmScalarType('B', jByteClass, 'byteValue')
  217. jChar = JvmScalarType('C', jCharClass, 'charValue')
  218. jShort = JvmScalarType('S', jShortClass, 'shortValue')
  219. class Generifier(object):
  220. """
  221. A utility class for working with generic methods in the OOTYPE
  222. system. You instantiate it with a given type, and you can ask it
  223. for the actual or erased types of any method of that type.
  224. """
  225. def __init__(self, OOTYPE):
  226. self.OOTYPE = OOTYPE
  227. # Make a hashtable mapping the generic parameter to a tuple:
  228. # (actual type, erased type)
  229. self.generics = {}
  230. if hasattr(self.OOTYPE, 'SELFTYPE_T'):
  231. self.generics[self.OOTYPE.SELFTYPE_T] = (self.OOTYPE,self.OOTYPE)
  232. for pname,pval in (('ITEMTYPE_T', 'ITEM'),
  233. ('KEYTYPE_T', '_KEYTYPE'),
  234. ('VALUETYPE_T', '_VALUETYPE')):
  235. if hasattr(self.OOTYPE, pname):
  236. placeholder = getattr(self.OOTYPE, pname)
  237. placeholder_val = getattr(self.OOTYPE, pval)
  238. self.generics[placeholder] = (placeholder_val, ootype.ROOT)
  239. def full_types(self, method_name):
  240. """
  241. Returns a tuple of argument and return types for the method
  242. named 'method_name'. These are the actual generic types. The
  243. set method for a list of strings, for example, might return:
  244. ( [INT, STRING], VOID )
  245. """
  246. GENMETH = self.OOTYPE._GENERIC_METHODS[method_name]
  247. ARGS, RESULT = (GENMETH.ARGS, GENMETH.RESULT)
  248. ARGS = [self.generics.get(X,(X,))[0] for X in ARGS]
  249. RESULT = self.generics.get(RESULT, (RESULT,))[0]
  250. return (ARGS, RESULT)
  251. def erased_types(self, method_name):
  252. """
  253. Returns a tuple of argument and return types for the method
  254. named 'method_name'. These are the erased generic types. The
  255. set method for a list of strings, for example, might return:
  256. ( [INT, OBJECT], VOID )
  257. """
  258. GENMETH = self.OOTYPE._GENERIC_METHODS[method_name]
  259. ARGS, RESULT = (GENMETH.ARGS, GENMETH.RESULT)
  260. ARGS = [self.generics.get(X,(None,X))[1] for X in ARGS]
  261. RESULT = self.generics.get(RESULT, (None,RESULT))[1]
  262. return (ARGS, RESULT)
  263. # ______________________________________________________________________
  264. # Java Callback Interfaces
  265. #
  266. # A list of interfaces which static functions that we generate will
  267. # automatically implement if applicable. See the pypy/Callback.java,
  268. # node.py/StaticMethodInterface for more information.
  269. jCallbackInterfaces = [] # collects all of the defined JvmCallbackInterfaces
  270. class JvmCallbackInterface(JvmInterfaceType):
  271. def __init__(self, name, jargtypes, jrettype):
  272. JvmInterfaceType.__init__(self, name)
  273. self.java_argument_types = jargtypes
  274. self.java_return_type = jrettype
  275. jCallbackInterfaces.append(self) # add to global list
  276. def matches(self, jargtypes, jrettype):
  277. """ Given a set of argument types and a return type for some
  278. static function defined by the user, returns true if this
  279. JvmCallbackInterface applies. Note that the types don't have
  280. to match exactly: we assume that (in the list of arguments)
  281. jObject is used as a wildcard, and some adaptation code may
  282. have to be inserted."""
  283. if len(self.java_argument_types) != len(jargtypes):
  284. return False
  285. for expjarg, actjarg in zip(self.java_argument_types, jargtypes):
  286. if expjarg == jObject: continue # hack: assume obj means any type
  287. if expjarg != actjarg: return False
  288. return jrettype == self.java_return_type
  289. jPyPyHashCode = JvmCallbackInterface('pypy.HashCode', [jObject], jInt)
  290. jPyPyEquals = JvmCallbackInterface('pypy.Equals', [jObject, jObject], jBool)
  291. class JvmNativeClass(JvmClassType):
  292. def __init__(self, db, OOTYPE):
  293. self.OOTYPE = OOTYPE
  294. self.db = db
  295. # XXX fixed java.lang?
  296. self.methods = {}
  297. JvmClassType.__init__(self, "java.util." + OOTYPE._name)
  298. self._add_methods()
  299. def __eq__(self, other):
  300. return isinstance(other, JvmNativeClass) and other.OOTYPE == self.OOTYPE
  301. def __hash__(self):
  302. return hash(("JvmNativeClass", self.OOTYPE))
  303. def lookup_field(self):
  304. XXX
  305. def lookup_method(self, methname):
  306. return self.methods[methname]
  307. def _add_methods(self):
  308. for methname, methspec in self.OOTYPE._class_._methods.items():
  309. argtypes = [self.db.annotation_to_cts(arg._type) for arg in
  310. methspec.args]
  311. restype = self.db.annotation_to_cts(methspec.retval._type)
  312. self.methods[methname] = Method.v(self, methname,
  313. argtypes, restype)
  314. # ______________________________________________________________________
  315. # The bridge between RPython array and JVM arrays. The main differences
  316. # are that (a) RPython has arrays of void type, and (b) RPython arrays
  317. # have methods, whereas Java methods don't. We inline those methods
  318. # into the appropriate bytecode.
  319. class _JvmVoidArray(JvmClassType):
  320. """
  321. A special case for void arrays. These are represented by an instance
  322. of the VoidArray class, which implements the required methods.
  323. """
  324. method_types = {
  325. 'll_length': ([], jInt),
  326. 'll_getitem_fast': ([jInt], jVoid),
  327. 'll_setitem_fast': ([jInt], jVoid),
  328. }
  329. def __init__(self):
  330. JvmClassType.__init__(self, 'pypy.VoidArray')
  331. def make(self, gen):
  332. # Construct a new VoidArray object, assuming the length has
  333. # been pushed onto the stack already.
  334. gen.emit(PYPYVOIDARRAYMAKE)
  335. def lookup_field(self, fieldnm):
  336. raise KeyError(fieldnm) # no fields
  337. def lookup_method(self, methodnm):
  338. jargtypes, jrettype = self.method_types[methodnm]
  339. return Method.v(self, methodnm, jargtypes, jrettype)
  340. class JvmArrayType(JvmType):
  341. """
  342. Subclass used for all array instances.
  343. """
  344. def __init__(self, elemtype):
  345. JvmType.__init__(self, desc_for_array_of(elemtype.descriptor))
  346. self.element_type = elemtype
  347. def make(self, gen):
  348. # Issues the opcode to build a new array of the appropriate type.
  349. # Assumes the length has been pushed onto the stack already.
  350. gen.emit(NEWARRAY.for_type(self))
  351. def lookup_field(self, fieldnm):
  352. raise KeyError(fieldnm)
  353. def lookup_method(self, methodnm):
  354. # Arrays don't have methods in Java, but they do in the ootype system
  355. if methodnm == "ll_length":
  356. return OpcodeMethod([], jInt, ARRAYLENGTH)
  357. elif methodnm == "ll_getitem_fast":
  358. return OpcodeMethod([jInt], self.element_type,
  359. ARRLOAD.for_type(self.element_type))
  360. elif methodnm == "ll_setitem_fast":
  361. return OpcodeMethod([jInt, self.element_type], jVoid,
  362. ARRSTORE.for_type(self.element_type))
  363. else:
  364. raise KeyError(methodnm)
  365. jBoolArray = JvmArrayType(jBool)
  366. jByteArray = JvmArrayType(jByte)
  367. jObjectArray = JvmArrayType(jObject)
  368. jStringArray = JvmArrayType(jString)
  369. jDoubleArray = JvmArrayType(jDouble)
  370. jCharArray = JvmArrayType(jChar)
  371. jIntArray = JvmArrayType(jInt)
  372. jVoidArray = _JvmVoidArray()
  373. # ______________________________________________________________________
  374. # Opcodes
  375. #
  376. # Objects describing the various opcodes which we use. In some cases,
  377. # there are also opcode families, which consist of a set of related
  378. # opcodes that are specialized by the types they operate on (i.e.,
  379. # IADD, DADD, etc).
  380. class Opcode(object):
  381. def __init__(self, jvmstr):
  382. """
  383. flags is a set of flags (see above) that describe opcode #UPDATE
  384. jvmstr is the name for jasmin printouts
  385. """
  386. self.jvmstr = jvmstr
  387. self.flags = None #Should flags be added to args?
  388. def __repr__(self):
  389. return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
  390. def specialize(self, args):
  391. """ Process the argument list according to the various flags.
  392. Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing
  393. the new opcode, and ARGS is a list of arguments or empty tuple.
  394. Most of these do not do anything. """
  395. return (self.jvmstr, args)
  396. class IntConstOpcode(Opcode):
  397. """ The ICONST opcode specializes itself for small integer opcodes. """
  398. def specialize(self, args):
  399. assert len(args) == 1
  400. if args[0] == -1:
  401. return self.jvmstr + "_m1", ()
  402. elif args[0] >= 0 and args[0] <= 5:
  403. return self.jvmstr + "_" + str(args[0]), ()
  404. # Non obvious: convert ICONST to LDC if the constant is out of
  405. # range
  406. return "ldc", args
  407. class VarOpcode(Opcode):
  408. """ An Opcode which takes a variable index as an argument; specialized
  409. to small integer indices. """
  410. def specialize(self, args):
  411. assert len(args) == 1
  412. if args[0] >= 0 and args[0] <= 3:
  413. return self.jvmstr + "_" + str(args[0]), ()
  414. return Opcode.specialize(self, args)
  415. class IntClassNameOpcode(Opcode):
  416. """ An opcode which takes an internal class name as its argument;
  417. the actual argument will be a JvmType instance. """
  418. def specialize(self, args):
  419. args = [args[0].descriptor.int_class_name()]
  420. return self.jvmstr, args
  421. class OpcodeFamily(object):
  422. """
  423. Many opcodes in JVM have variants that depend on the type of the
  424. operands; for example, one must choose the correct ALOAD, ILOAD,
  425. or DLOAD depending on whether one is loading a reference, integer,
  426. or double variable respectively. Each instance of this class
  427. defines one 'family' of opcodes, such as the LOAD family shown
  428. above, and produces Opcode objects specific to a particular type.
  429. """
  430. def __init__(self, opcclass, suffix):
  431. """
  432. opcclass is the opcode subclass to use (see above) when
  433. instantiating a particular opcode
  434. jvmstr is the name for jasmin printouts
  435. """
  436. self.opcode_class = opcclass
  437. self.suffix = suffix
  438. self.cache = {}
  439. def _o(self, prefix):
  440. try:
  441. return self.cache[prefix]
  442. except KeyError:
  443. self.cache[prefix] = obj = self.opcode_class(
  444. prefix+self.suffix)
  445. return obj
  446. def for_type(self, argtype):
  447. """ Returns a customized opcode of this family appropriate to
  448. 'argtype', a JvmType object. """
  449. desc = argtype.descriptor
  450. # These are always true:
  451. if desc[0] == 'L': return self._o("a") # Objects
  452. if desc[0] == '[': return self._o("a") # Arrays
  453. if desc == 'I': return self._o("i") # Integers
  454. if desc == 'J': return self._o("l") # Integers
  455. if desc == 'D': return self._o("d") # Doubles
  456. if desc == 'V': return self._o("") # Void [used by RETURN]
  457. # Chars/Bytes/Booleans are normally represented as ints
  458. # in the JVM, but some opcodes are different. They use a
  459. # different OpcodeFamily (see ArrayOpcodeFamily for ex)
  460. if desc == 'C': return self._o("i") # Characters
  461. if desc == 'B': return self._o("i") # Bytes
  462. if desc == 'Z': return self._o("i") # Boolean
  463. if desc == 'S': return self._o("i") # Short
  464. assert False, "Unknown argtype=%s" % repr(argtype)
  465. raise NotImplementedError
  466. class ArrayOpcodeFamily(OpcodeFamily):
  467. """ Opcode family specialized for array access instr """
  468. def for_type(self, argtype):
  469. desc = argtype.descriptor
  470. if desc == 'J': return self._o("l") # Integers
  471. if desc == 'D': return self._o("d") # Doubles
  472. if desc == 'C': return self._o("c") # Characters
  473. if desc == 'B': return self._o("b") # Bytes
  474. if desc == 'Z': return self._o("b") # Boolean (access as bytes)
  475. return OpcodeFamily.for_type(self, argtype)
  476. class NewArrayOpcodeFamily(object):
  477. def __init__(self):
  478. self.cache = {}
  479. def for_type(self, arraytype):
  480. try:
  481. return self.cache[arraytype]
  482. except KeyError:
  483. pass
  484. desc = arraytype.descriptor
  485. if desc == '[I':
  486. s = "newarray int"
  487. elif desc == '[D':
  488. s = "newarray double"
  489. elif desc == '[C':
  490. s = "newarray char"
  491. elif desc == '[B':
  492. s = "newarray byte"
  493. elif desc == '[Z':
  494. s = "newarray boolean"
  495. else:
  496. s = "anewarray " + arraytype.element_type.descriptor.int_class_name()
  497. self.cache[arraytype] = obj = Opcode(s)
  498. return obj
  499. NEWARRAY = NewArrayOpcodeFamily()
  500. ARRAYLENGTH = Opcode("arraylength")
  501. # Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx
  502. # variants compare a single integer arg against 0, and the IF_ICMPxx
  503. # variants compare 2 integer arguments against each other.
  504. for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'):
  505. ifop = "if%s" % cmpop
  506. if_icmpop = "if_icmp%s" % cmpop
  507. globals()[ifop.upper()] = Opcode(ifop)
  508. globals()[if_icmpop.upper()] = Opcode(if_icmpop)
  509. # Compare references, either against NULL or against each other
  510. IFNULL = Opcode('ifnull')
  511. IFNONNULL = Opcode('ifnonnull')
  512. IF_ACMPEQ = Opcode('if_acmpeq')
  513. IF_ACMPNE = Opcode('if_acmpne')
  514. # Method invocation
  515. INVOKESTATIC = Opcode('invokestatic')
  516. INVOKEVIRTUAL = Opcode('invokevirtual')
  517. INVOKESPECIAL = Opcode('invokespecial')
  518. INVOKEINTERFACE = Opcode('invokeinterface')
  519. # Other opcodes
  520. LDC = Opcode('ldc') # single-word types
  521. LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs
  522. GOTO = Opcode('goto')
  523. ICONST = IntConstOpcode('iconst')
  524. ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly
  525. ACONST_NULL=Opcode('aconst_null')
  526. DCONST_0 = Opcode('dconst_0')
  527. DCONST_1 = Opcode('dconst_1')
  528. LCONST_0 = Opcode('lconst_0')
  529. LCONST_1 = Opcode('lconst_1')
  530. GETFIELD = Opcode('getfield')
  531. PUTFIELD = Opcode('putfield')
  532. GETSTATIC = Opcode('getstatic')
  533. PUTSTATIC = Opcode('putstatic')
  534. CHECKCAST = IntClassNameOpcode('checkcast')
  535. INEG = Opcode('ineg')
  536. IXOR = Opcode('ixor')
  537. IADD = Opcode('iadd')
  538. ISUB = Opcode('isub')
  539. IMUL = Opcode('imul')
  540. IDIV = Opcode('idiv')
  541. IREM = Opcode('irem')
  542. IAND = Opcode('iand')
  543. IOR = Opcode('ior')
  544. ISHL = Opcode('ishl')
  545. ISHR = Opcode('ishr')
  546. IUSHR = Opcode('iushr')
  547. LCMP = Opcode('lcmp')
  548. DCMPG = Opcode('dcmpg')
  549. DCMPL = Opcode('dcmpl')
  550. NOP = Opcode('nop')
  551. I2D = Opcode('i2d')
  552. I2L = Opcode('i2l')
  553. I2S = Opcode('i2s')
  554. D2I= Opcode('d2i')
  555. #D2L= Opcode('d2l') #PAUL
  556. L2I = Opcode('l2i')
  557. L2D = Opcode('l2d')
  558. ATHROW = Opcode('athrow')
  559. DNEG = Opcode('dneg')
  560. DADD = Opcode('dadd')
  561. DSUB = Opcode('dsub')
  562. DMUL = Opcode('dmul')
  563. DDIV = Opcode('ddiv')
  564. DREM = Opcode('drem')
  565. LNEG = Opcode('lneg')
  566. LADD = Opcode('ladd')
  567. LSUB = Opcode('lsub')
  568. LMUL = Opcode('lmul')
  569. LDIV = Opcode('ldiv')
  570. LREM = Opcode('lrem')
  571. LAND = Opcode('land')
  572. LOR = Opcode('lor')
  573. LXOR = Opcode('lxor')
  574. LSHL = Opcode('lshl')
  575. LSHR = Opcode('lshr')
  576. LUSHR = Opcode('lushr')
  577. NEW = IntClassNameOpcode('new')
  578. DUP = Opcode('dup')
  579. DUP2 = Opcode('dup2')
  580. DUP_X1 = Opcode('dup_x1')
  581. POP = Opcode('pop')
  582. POP2 = Opcode('pop2')
  583. SWAP = Opcode('swap')
  584. INSTANCEOF= IntClassNameOpcode('instanceof')
  585. # Loading/storing local variables
  586. LOAD = OpcodeFamily(VarOpcode, "load")
  587. STORE = OpcodeFamily(VarOpcode, "store")
  588. RETURN = OpcodeFamily(Opcode, "return")
  589. # Loading/storing from arrays
  590. # *NOTE*: This family is characterized by the type of the ELEMENT,
  591. # not the type of the ARRAY.
  592. #
  593. # Also: here I break from convention by naming the objects ARRLOAD
  594. # rather than ALOAD, even though the suffix is 'aload'. This is to
  595. # avoid confusion with the ALOAD opcode.
  596. ARRLOAD = ArrayOpcodeFamily(Opcode, "aload")
  597. ARRSTORE = ArrayOpcodeFamily(Opcode, "astore")
  598. # ______________________________________________________________________
  599. # Methods and Fields
  600. #
  601. # These structures are used throughout the code to refer to JVM
  602. # methods and fields. Similarly to JvmType instances, they are used
  603. # both to represent random fields/methods in the JVM, and to represent
  604. # the translation of an OOTYPE field/method. Therefore, these may not
  605. # actually generate code corresponding to a real JVM method: for
  606. # example, arrays use a BaseMethod subclass to generate the
  607. # appropriate JVM opcodes that correspond to RPython arrays.
  608. # Likewise, the Property class (see below) allows us to use a pair of
  609. # JVM methods to represent an OOTYPE field.
  610. class BaseMethod(object):
  611. def __init__(self, argtypes, rettype):
  612. self.argument_types = argtypes # List of jvmtypes
  613. self.return_type = rettype # jvmtype
  614. def is_static(self):
  615. raise NotImplementedError
  616. def invoke(self, gen):
  617. raise NotImplementedError
  618. class OpcodeMethod(BaseMethod):
  619. """
  620. Represents a "method" that is actually implemented by a single opcode,
  621. such as ARRAYLENGTH
  622. """
  623. def __init__(self, argtypes, rettype, opcode, static=False):
  624. """
  625. argtypes = an array of jvm types indicating what we expect on stack
  626. rettype = the type we will push on the stack (if any)
  627. opcode = the opcode to emit
  628. static = should we be considered static? if true, then we will
  629. not push the receiver onto the stack in metavm
  630. """
  631. BaseMethod.__init__(self, argtypes, rettype)
  632. self.opcode = opcode
  633. self.static = static
  634. def is_static(self):
  635. return self.static
  636. def invoke(self, gen):
  637. gen.emit(self.opcode)
  638. class Method(BaseMethod):
  639. """
  640. Represents a method implemented by a genuine JVM method. Unlike
  641. OpcodeMethod, when we emit the opcode this class is an argument to
  642. it, and contains the extra info about the class/method being
  643. invoked that is required.
  644. """
  645. # Create a constructor:
  646. def c(classty, argtypes):
  647. return Method(classty.name, "<init>", argtypes, jVoid,
  648. opcode=INVOKESPECIAL)
  649. c = staticmethod(c)
  650. # Create a virtual or interface method:
  651. def v(classty, methnm, argtypes, rettype):
  652. """
  653. Shorthand to create a virtual method.
  654. 'class' - JvmType object for the class
  655. 'methnm' - name of the method (Python string)
  656. 'argtypes' - list of JvmType objects, one for each argument but
  657. not the this ptr
  658. 'rettype' - JvmType for return type
  659. """
  660. assert argtypes is not None
  661. assert rettype is not None
  662. classnm = classty.name
  663. if isinstance(classty, JvmInterfaceType):
  664. opc = INVOKEINTERFACE
  665. else:
  666. assert isinstance(classty, JvmClassType)
  667. opc = INVOKEVIRTUAL
  668. return Method(classnm, methnm, argtypes, rettype, opcode=opc)
  669. v = staticmethod(v)
  670. # Create a static method:
  671. def s(classty, methnm, argtypes, rettype):
  672. """
  673. Shorthand to create a static method.
  674. 'class' - JvmType object for the class
  675. 'methnm' - name of the method (Python string)
  676. 'argtypes' - list of JvmType objects, one for each argument but
  677. not the this ptr
  678. 'rettype' - JvmType for return type
  679. """
  680. assert isinstance(classty, JvmType)
  681. classnm = classty.name
  682. return Method(classnm, methnm, argtypes, rettype)
  683. s = staticmethod(s)
  684. def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC):
  685. BaseMethod.__init__(self, argtypes, rettype)
  686. self.opcode = opcode
  687. self.class_name = classnm # String, ie. "java.lang.Math"
  688. self.method_name = methnm # String "abs"
  689. # Compute the method descriptior, which is a string like "()I":
  690. argtypesdesc = [a.descriptor for a in argtypes]
  691. rettypedesc = rettype.descriptor
  692. self.descriptor = desc_for_method(argtypesdesc, rettypedesc)
  693. def invoke(self, gen):
  694. gen._instr(self.opcode, self)
  695. def is_static(self):
  696. return self.opcode == INVOKESTATIC
  697. def jasmin_syntax(self):
  698. res = "%s/%s%s" % (self.class_name.replace('.','/'),
  699. self.method_name,
  700. self.descriptor)
  701. # A weird, inexplicable quirk of Jasmin syntax is that it requires
  702. # the number of arguments after an invokeinterface call:
  703. if self.opcode == INVOKEINTERFACE:
  704. res += " %d" % (len(self.argument_types)+1,)
  705. return res
  706. class Field(object):
  707. """
  708. Represents an actual JVM field. Use the methods
  709. fld.load(gen) / gen.emit(fld)
  710. or
  711. fld.store(gen)
  712. to load the field's value onto the stack, or store into the field.
  713. If this is not a static field, you must have pushed the object
  714. containing the field and the field's value first.
  715. See also Property.
  716. """
  717. @staticmethod
  718. def i(classty, fieldnm, fieldty, OOTYPE=None):
  719. """
  720. Shorthand to create an instance field.
  721. 'class' - JvmType object for the class containing the field
  722. 'fieldnm' - name of the field (Python string)
  723. 'fieldty' - JvmType object for the type of the field
  724. 'OOTYPE' - optional OOTYPE object for the type of the field
  725. """
  726. return Field(classty.name, fieldnm, fieldty, False, OOTYPE)
  727. @staticmethod
  728. def s(classty, fieldnm, fieldty, OOTYPE=None):
  729. """
  730. Shorthand to create a static field.
  731. 'class' - JvmType object for the class containing the field
  732. 'fieldnm' - name of the field (Python string)
  733. 'fieldty' - JvmType object for the type of the field
  734. 'OOTYPE' - optional OOTYPE object for the type of the field
  735. """
  736. return Field(classty.name, fieldnm, fieldty, True, OOTYPE)
  737. def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None):
  738. # All fields are public
  739. self.class_name = classnm # String, ie. "java.lang.Math"
  740. self.field_name = fieldnm # String "someField"
  741. self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None
  742. self.jtype = jtype # JvmType
  743. self.is_static = static # True or False
  744. def load(self, gen):
  745. if self.is_static:
  746. gen._instr(GETSTATIC, self)
  747. else:
  748. gen._instr(GETFIELD, self)
  749. def store(self, gen):
  750. if self.is_static:
  751. gen._instr(PUTSTATIC, self)
  752. else:
  753. gen._instr(PUTFIELD, self)
  754. def jasmin_syntax(self):
  755. return "%s/%s %s" % (
  756. self.class_name.replace('.','/'),
  757. self.field_name,
  758. self.jtype.descriptor)
  759. class Property(object):
  760. """
  761. An object which acts like a Field, but when a value is loaded or
  762. stored it actually invokes accessor methods. Use like a field
  763. (prop.load(gen), prop.store(gen), etc).
  764. """
  765. def __init__(self, field_name, get_method, put_method, OOTYPE=None):
  766. self.get_method = get_method
  767. self.put_method = put_method
  768. self.field_name = field_name
  769. self.OOTYPE = OOTYPE
  770. # Synthesize the Field attributes from the get_method/put_method:
  771. self.class_name = get_method.class_name
  772. assert put_method.class_name == self.class_name
  773. self.jtype = get_method.return_type
  774. self.is_static = get_method.is_static
  775. def load(self, gen):
  776. self.get_method.invoke(gen)
  777. def store(self, gen):
  778. self.put_method.invoke(gen)
  779. # jasmin_syntax is not needed, since this object itself never appears
  780. # as an argument an Opcode
  781. # ___________________________________________________________________________
  782. # Methods
  783. #
  784. # "Method" objects describe all the information needed to invoke a
  785. # method. We create one for each node.Function object, as well as for
  786. # various helper methods (defined below). To invoke a method, you
  787. # push its arguments and then use generator.emit(methobj) where
  788. # methobj is its Method instance.
  789. OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt)
  790. OBJTOSTRING = Method.v(jObject, 'toString', (), jString)
  791. OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool)
  792. SYSTEMIDENTITYHASH = Method.s(jSystem, 'identityHashCode', (jObject,), jInt)
  793. SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid)
  794. INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString)
  795. SHORTTOSTRINGS = Method.s(jShortClass, 'toString', (jShort,), jString)
  796. LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString)
  797. DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString)
  798. CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString)
  799. MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt)
  800. IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt)
  801. MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong)
  802. LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong)
  803. MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble)
  804. INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt)
  805. LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong)
  806. IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt)
  807. LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong)
  808. ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt)
  809. LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong)
  810. IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
  811. LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
  812. MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble)
  813. IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
  814. LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
  815. IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
  816. LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
  817. IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
  818. LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
  819. ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt)
  820. LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong)
  821. MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble)
  822. PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid)
  823. CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass)
  824. CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
  825. STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append',
  826. (jString,), jStringBuilder)
  827. PYPYINTBETWEEN = Method.s(jPyPy, 'int_between', (jInt,jInt,jInt), jBool)
  828. PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
  829. PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
  830. PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
  831. PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
  832. PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
  833. PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
  834. PYPYUINTTOLONG = Method.s(jPyPy, 'uint_to_long', (jInt,), jLong)
  835. PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
  836. PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
  837. PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
  838. PYPYDOUBLETOULONG = Method.s(jPyPy, 'double_to_ulong', (jDouble,), jLong)
  839. PYPYULONGTODOUBLE = Method.s(jPyPy, 'ulong_to_double', (jLong,), jDouble)
  840. PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
  841. PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt)
  842. PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt)
  843. PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong)
  844. PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong)
  845. PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool)
  846. PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble)
  847. PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar)
  848. PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble)
  849. PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid)
  850. PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
  851. PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString)
  852. PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
  853. PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString)
  854. PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString)
  855. PYPYSERIALIZEDOUBLE = Method.s(jPyPy, 'serialize_double', (jDouble,), jString)
  856. PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString)
  857. PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString)
  858. PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString)
  859. PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString)
  860. PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString)
  861. PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
  862. PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
  863. PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList)
  864. PYPYBOXINT = Method.s(jPyPy, 'box_integer', (jInt,), jObject)
  865. PYPYUNBOXINT = Method.s(jPyPy, 'unbox_integer', (jObject,), jInt)
  866. PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble)
  867. OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass)
  868. CLASSGETNAME = Method.v(jClass, 'getName', (), jString)
  869. CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make',
  870. (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict)
  871. PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef)
  872. PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject)
  873. PYPYVOIDARRAYMAKE = Method.s(jVoidArray, 'make', (jInt,), jVoidArray)
  874. # ___________________________________________________________________________
  875. # Fields
  876. #
  877. # Field objects encode information about fields.
  878. SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream)
  879. SYSTEMERR = Field.s(jSystem, 'err', jPrintStream)
  880. DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble)
  881. DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble)
  882. DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble)
  883. PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink)
  884. PYPYOS = Field.i(jPyPy, 'os', jll_os)