[pypy-svn] r49216 - in pypy/dist/pypy/translator: cli/test jvm jvm/src/pypy oosupport oosupport/test_template

niko at codespeak.net niko at codespeak.net
Thu Nov 29 23:20:40 CET 2007


Author: niko
Date: Thu Nov 29 23:20:37 2007
New Revision: 49216

Modified:
   pypy/dist/pypy/translator/cli/test/test_builtin.py
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/metavm.py
   pypy/dist/pypy/translator/jvm/methods.py
   pypy/dist/pypy/translator/jvm/node.py
   pypy/dist/pypy/translator/jvm/opcodes.py
   pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
   pypy/dist/pypy/translator/jvm/src/pypy/ll_os.java
   pypy/dist/pypy/translator/jvm/typesystem.py
   pypy/dist/pypy/translator/oosupport/metavm.py
   pypy/dist/pypy/translator/oosupport/test_template/builtin.py
   pypy/dist/pypy/translator/oosupport/test_template/constant.py
Log:
Refactor so that we can support multiple interpreters simultaneously.
Instead of storing the interlink interface in a static field of PyPy.java,
we now create a new instance of PyPy.java which has a custom interlink,
and then dispatch to that as needed.  This means that different PyPy
interpters can each have their own PyPy instance customized to their
specific interlink class.



Modified: pypy/dist/pypy/translator/cli/test/test_builtin.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_builtin.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_builtin.py	Thu Nov 29 23:20:37 2007
@@ -12,7 +12,6 @@
         py.test.skip("Doesn't work on Windows, yet")
 
 class TestCliBuiltin(CliTest, BaseTestBuiltin):
-    test_os_dup = skip_os
     test_os_path_exists = skip_os
     test_os_isdir = skip_os
 

Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Thu Nov 29 23:20:37 2007
@@ -15,7 +15,7 @@
 import pypy.translator.jvm.constant as jvmconst
 from pypy.translator.jvm.typesystem import \
      jStringBuilder, jInt, jVoid, jString, jChar, jObject, \
-     jThrowable, JvmNativeClass
+     jThrowable, JvmNativeClass, jPyPy, JvmClassType
 from pypy.translator.jvm.builtin import JvmBuiltInType
 
 from pypy.translator.oosupport.database import Database as OODatabase
@@ -51,6 +51,18 @@
         self._object_impl = None
         self._object_exc_impl = None
 
+        # Create information about the Main class we will build:
+        #
+        #    note that it will have a static field called 'pypy' that
+        #    points to a PyPy instance.  This PyPy instance has been
+        #    paired with the appropriate Interlink implementation
+        #    which allows it to create generated structures.
+        #
+        #    These are public attributes that are referenced from
+        #    elsewhere in the code.
+        self.jPyPyMain = JvmClassType(self._pkg('Main'))
+        self.pypy_field = jvmgen.Field.s(self.jPyPyMain, 'pypy', jPyPy)
+
     # _________________________________________________________________
     # Java String vs Byte Array
     #
@@ -108,7 +120,7 @@
         for method_name, helper in methods.items():
             cls.add_method(node.InterlinkFunction(cls, method_name, helper))
         cls.add_interface(jvmtype.jPyPyInterlink)
-        self.interlink_class = cls
+        self.jInterlinkImplementation = cls
         self.pending_node(cls)
 
     def types_for_graph(self, graph):

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Thu Nov 29 23:20:37 2007
@@ -13,7 +13,7 @@
      jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \
      jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \
      jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \
-     jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os
+     jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink
 
 
 # ___________________________________________________________________________
@@ -267,7 +267,7 @@
                       opcode=INVOKESPECIAL)
     c = staticmethod(c)
 
-    # Create a virtual method:
+    # Create a virtual or interface method:
     def v(classty, methnm, argtypes, rettype):
         """
         Shorthand to create a virtual method.
@@ -337,56 +337,56 @@
 DOUBLETOSTRINGD =       Method.s(jDoubleClass, 'toString', (jDouble,), jString)
 CHARTOSTRINGC =         Method.s(jCharClass, 'toString', (jChar,), jString)
 MATHIABS =              Method.s(jMath, 'abs', (jInt,), jInt)
-IABSOVF =               Method.s(jPyPy, 'abs_ovf', (jInt,), jInt)
+IABSOVF =               Method.v(jPyPy, 'abs_ovf', (jInt,), jInt)
 MATHLABS =              Method.s(jMath, 'abs', (jLong,), jLong)
-LABSOVF =               Method.s(jPyPy, 'abs_ovf', (jLong,), jLong)
+LABSOVF =               Method.v(jPyPy, 'abs_ovf', (jLong,), jLong)
 MATHDABS =              Method.s(jMath, 'abs', (jDouble,), jDouble)
-INEGOVF =               Method.s(jPyPy, 'negate_ovf', (jInt,), jInt)
-LNEGOVF =               Method.s(jPyPy, 'negate_ovf', (jLong,), jLong)
-IADDOVF =               Method.s(jPyPy, 'add_ovf', (jInt, jInt), jInt)
-LADDOVF =               Method.s(jPyPy, 'add_ovf', (jLong, jLong), jLong)
-ISUBOVF =               Method.s(jPyPy, 'subtract_ovf', (jInt, jInt), jInt)
-LSUBOVF =               Method.s(jPyPy, 'subtract_ovf', (jLong, jLong), jLong)
-IMULOVF =               Method.s(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
-LMULOVF =               Method.s(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
+INEGOVF =               Method.v(jPyPy, 'negate_ovf', (jInt,), jInt)
+LNEGOVF =               Method.v(jPyPy, 'negate_ovf', (jLong,), jLong)
+IADDOVF =               Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt)
+LADDOVF =               Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong)
+ISUBOVF =               Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt)
+LSUBOVF =               Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong)
+IMULOVF =               Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
+LMULOVF =               Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
 MATHFLOOR =             Method.s(jMath, 'floor', (jDouble,), jDouble)
-IFLOORDIVOVF =          Method.s(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
-LFLOORDIVOVF =          Method.s(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
-IFLOORDIVZEROVF =       Method.s(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
-LFLOORDIVZEROVF =       Method.s(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
-IREMOVF =               Method.s(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
-LREMOVF =               Method.s(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
-ISHLOVF =               Method.s(jPyPy, 'lshift_ovf', (jInt, jInt), jInt)
-LSHLOVF =               Method.s(jPyPy, 'lshift_ovf', (jLong, jLong), jLong)
+IFLOORDIVOVF =          Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
+LFLOORDIVOVF =          Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
+IFLOORDIVZEROVF =       Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
+LFLOORDIVZEROVF =       Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
+IREMOVF =               Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
+LREMOVF =               Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
+ISHLOVF =               Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt)
+LSHLOVF =               Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong)
 MATHDPOW =              Method.s(jMath, 'pow', (jDouble, jDouble), jDouble)
 PRINTSTREAMPRINTSTR =   Method.v(jPrintStream, 'print', (jString,), jVoid)
 CLASSFORNAME =          Method.s(jClass, 'forName', (jString,), jClass)
 CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
-PYPYAPPEND =            Method.s(jPyPy, 'append',
-                                 (jStringBuilder, jString), jVoid)
+STRINGBUILDERAPPEND =   Method.v(jStringBuilder, 'append',
+                                 (jString,), jStringBuilder)
 PYPYUINTCMP =           Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
 PYPYULONGCMP =          Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
-PYPYUINTMOD =           Method.s(jPyPy, 'uint_mod', (jInt, jInt), jInt)
-PYPYUINTMUL =           Method.s(jPyPy, 'uint_mul', (jInt, jInt), jInt)
-PYPYUINTDIV =           Method.s(jPyPy, 'uint_div', (jInt, jInt), jInt)
-PYPYULONGMOD =          Method.s(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
+PYPYUINTMOD =           Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
+PYPYUINTMUL =           Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
+PYPYUINTDIV =           Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
+PYPYULONGMOD =          Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
 PYPYUINTTODOUBLE =      Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
 PYPYDOUBLETOUINT =      Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
-PYPYDOUBLETOLONG =      Method.s(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
-PYPYLONGBITWISENEGATE = Method.s(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
-PYPYSTRTOINT =          Method.s(jPyPy, 'str_to_int', (jString,), jInt)
-PYPYSTRTOUINT =         Method.s(jPyPy, 'str_to_uint', (jString,), jInt)
-PYPYSTRTOLONG =         Method.s(jPyPy, 'str_to_long', (jString,), jLong)
-PYPYSTRTOULONG =        Method.s(jPyPy, 'str_to_ulong', (jString,), jLong)
-PYPYSTRTOBOOL =         Method.s(jPyPy, 'str_to_bool', (jString,), jBool)
-PYPYSTRTODOUBLE =       Method.s(jPyPy, 'str_to_double', (jString,), jDouble)
-PYPYSTRTOCHAR =         Method.s(jPyPy, 'str_to_char', (jString,), jChar)
-PYPYBOOLTODOUBLE =      Method.s(jPyPy, 'bool_to_double', (jBool,), jDouble)
+PYPYDOUBLETOLONG =      Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
+PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
+PYPYSTRTOINT =          Method.v(jPyPy, 'str_to_int', (jString,), jInt)
+PYPYSTRTOUINT =         Method.v(jPyPy, 'str_to_uint', (jString,), jInt)
+PYPYSTRTOLONG =         Method.v(jPyPy, 'str_to_long', (jString,), jLong)
+PYPYSTRTOULONG =        Method.v(jPyPy, 'str_to_ulong', (jString,), jLong)
+PYPYSTRTOBOOL =         Method.v(jPyPy, 'str_to_bool', (jString,), jBool)
+PYPYSTRTODOUBLE =       Method.v(jPyPy, 'str_to_double', (jString,), jDouble)
+PYPYSTRTOCHAR =         Method.v(jPyPy, 'str_to_char', (jString,), jChar)
+PYPYBOOLTODOUBLE =      Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble)
 PYPYDUMP          =     Method.s(jPyPy, 'dump', (jString,), jVoid)
 PYPYDUMPEXCWRAPPER =    Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
 PYPYSERIALIZEBOOLEAN =  Method.s(jPyPy, 'serialize_boolean', (jBool,), jString)
 PYPYSERIALIZEUINT  =    Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
-PYPYSERIALIZEULONG =    Method.s(jPyPy, 'serialize_ulonglong', (jLong,), jString)
+PYPYSERIALIZEULONG =    Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString)
 PYPYSERIALIZEVOID =     Method.s(jPyPy, 'serialize_void', (), jString)
 PYPYESCAPEDCHAR =       Method.s(jPyPy, 'escaped_char', (jChar,), jString)
 PYPYESCAPEDUNICHAR =    Method.s(jPyPy, 'escaped_unichar', (jChar,), jString)
@@ -396,13 +396,13 @@
 PYPYRUNTIMENEW =        Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
 PYPYSTRING2BYTES =      Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
 PYPYARRAYTOLIST =       Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList)
-PYPYOOPARSEFLOAT =      Method.s(jPyPy, 'ooparse_float', (jString,), jDouble)
+PYPYOOPARSEFLOAT =      Method.v(jPyPy, 'ooparse_float', (jString,), jDouble)
 OBJECTGETCLASS =        Method.v(jObject, 'getClass', (), jClass)
 CLASSGETNAME =          Method.v(jClass, 'getName', (), jString)
 CUSTOMDICTMAKE =        Method.s(jPyPyCustomDict, 'make',
                                  (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict)
 PYPYWEAKREFCREATE =     Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef)
-PYPYWEAKREFGET =        Method.v(jPyPyWeakRef, 'll_get', (), jObject)
+PYPYWEAKREFGET =        Method.s(jPyPyWeakRef, 'll_get', (), jObject)
 
 # ___________________________________________________________________________
 # Fields
@@ -410,6 +410,29 @@
 # Field objects encode information about fields.
 
 class Field(object):
+
+    @staticmethod
+    def i(classty, fieldnm, fieldty, OOTYPE=None):
+        """
+        Shorthand to create an instance field.
+        'class' - JvmType object for the class containing the field
+        'fieldnm' - name of the field (Python string)
+        'fieldty' - JvmType object for the type of the field
+        'OOTYPE' - optional OOTYPE object for the type of the field
+        """
+        return Field(classty.name, fieldnm, fieldty, False, OOTYPE)
+    
+    @staticmethod
+    def s(classty, fieldnm, fieldty, OOTYPE=None):
+        """
+        Shorthand to create a static field.
+        'class' - JvmType object for the class containing the field
+        'fieldnm' - name of the field (Python string)
+        'fieldty' - JvmType object for the type of the field
+        'OOTYPE' - optional OOTYPE object for the type of the field
+        """
+        return Field(classty.name, fieldnm, fieldty, True, OOTYPE)
+
     def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None):
         # All fields are public
         self.class_name = classnm  # String, ie. "java.lang.Math"
@@ -456,13 +479,14 @@
     # jasmin_syntax is not needed, since this object itself never appears
     # as an argument an Opcode
 
-SYSTEMOUT =    Field('java.lang.System', 'out', jPrintStream, True)
-SYSTEMERR =    Field('java.lang.System', 'err', jPrintStream, True)
-DOUBLENAN =    Field('java.lang.Double', 'NaN', jDouble, True)
-DOUBLEPOSINF = Field('java.lang.Double', 'POSITIVE_INFINITY', jDouble, True)
-DOUBLENEGINF = Field('java.lang.Double', 'NEGATIVE_INFINITY', jDouble, True)
+SYSTEMOUT =    Field.s(jSystem, 'out', jPrintStream)
+SYSTEMERR =    Field.s(jSystem, 'err', jPrintStream)
+DOUBLENAN =    Field.s(jDoubleClass, 'NaN', jDouble)
+DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble)
+DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble)
 
-PYPYINTERLINK= Field(jPyPy.name, 'interlink', jPyPyInterlink, True)
+PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink)
+PYPYOS =       Field.i(jPyPy, 'os', jll_os)
 
 # ___________________________________________________________________________
 # Generator State
@@ -941,6 +965,11 @@
         fieldobj = clsobj.lookup_field(fieldname)
         fieldobj.store(self)
 
+    def push_pypy(self):
+        """ Pushes the PyPy object which contains all of our helper methods
+        onto the stack """
+        self.db.pypy_field.load(self)
+
     def get_field(self, CONCRETETYPE, fieldname):
         clsobj = self.db.pending_class(CONCRETETYPE)
         fieldobj = clsobj.lookup_field(fieldname)
@@ -999,16 +1028,29 @@
             # we have to "deal with it"
             self.prepare_generic_result(RETTYPE)
 
+    def prepare_call_primitive(self, op, module, name):
+        # Load the PyPy object pointer onto the stack:
+        self.push_pypy()
+
+        # If necessary, load the ll_os object pointer instead:
+        if module == 'll_os':
+            PYPYOS.load(self)
+        
     def call_primitive(self, op, module, name):
         callee = op.args[0].value
-        argtypes, rettype = self.db.types_for_signature(callee._TYPE.ARGS, callee._TYPE.RESULT)
+        argtypes, rettype = self.db.types_for_signature(
+            callee._TYPE.ARGS, callee._TYPE.RESULT)
         if module == 'll_os':
             jcls = jll_os
         else:
             jcls = jPyPy
-        mthd = Method.s(jcls, name, argtypes, rettype)
+        mthd = Method.v(jcls, name, argtypes, rettype)
         self.emit(mthd)
 
+    def prepare_call_oostring(self, OOTYPE):
+        # Load the PyPy object pointer onto the stack:
+        self.push_pypy()
+
     def call_oostring(self, OOTYPE):
         cts_type = self.db.lltype_to_cts(OOTYPE)
 
@@ -1016,14 +1058,18 @@
         if isinstance(cts_type, jvmtype.JvmClassType):
             cts_type = jObject
             
-        mthd = Method.s(jPyPy, 'oostring', [cts_type, jInt], jString)
+        mthd = Method.v(jPyPy, 'oostring', [cts_type, jInt], jString)
         self.emit(mthd)
         if self.db.using_byte_array:
             self.emit(PYPYSTRING2BYTES)
 
+    def prepare_call_oounicode(self, OOTYPE):
+        # Load the PyPy object pointer onto the stack:
+        self.push_pypy()
+
     def call_oounicode(self, OOTYPE):
         cts_type = self.db.lltype_to_cts(OOTYPE)
-        mthd = Method.s(jPyPy, 'oounicode', [cts_type], jString)
+        mthd = Method.v(jPyPy, 'oounicode', [cts_type], jString)
         self.emit(mthd)
         if self.db.using_byte_array:
             self.emit(PYPYSTRING2BYTES)
@@ -1032,8 +1078,9 @@
         jtype = self.db.lltype_to_cts(TYPE)
         self.new_with_jtype(jtype)
 
-    def new_with_jtype(self, jtype):
-        ctor = Method.c(jtype, ())
+    def new_with_jtype(self, jtype, ctor=None):
+        if ctor is None:
+            ctor = Method.c(jtype, ())
         self.emit(NEW, jtype)
         self.emit(DUP)
         self.emit(ctor)

Modified: pypy/dist/pypy/translator/jvm/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/metavm.py	(original)
+++ pypy/dist/pypy/translator/jvm/metavm.py	Thu Nov 29 23:20:37 2007
@@ -69,11 +69,12 @@
         jexc: the JvmType of the exception
         pexcmthd: the name of the method on the PyPy object to call.
         The PyPy method must take no arguments, return void, and must
-        always throw an exception in practice.
+        always throw an exception in practice.  It would be better to
+        just find the class to throw normally, but I don't know how.
         """
         self.java_exc = jexc
-        self.pypy_method = jvmgen.Method.s(
-            jvmtype.jPyPy, pexcmthd, [], jvmtype.jVoid)
+        self.pypy_method = jvmgen.Method.v(
+            jvmtype.jPyPyInterlink, pexcmthd, [], jvmtype.jVoid)
         self.instruction = inst
         
     def render(self, gen, op):
@@ -87,8 +88,10 @@
         gen.goto(donelbl)
         # } catch (JavaExceptionType) {
         gen.mark(catchlbl)
-        gen.emit(jvmgen.POP)
-        gen.emit(self.pypy_method)
+        gen.emit(jvmgen.POP)            # throw away the exception object
+        gen.push_pypy()                 # load the PyPy object
+        gen.emit(jvmgen.PYPYINTERLINK)  # load the interlink field from it
+        gen.emit(self.pypy_method)      # invoke the method
         # Note: these instructions will never execute, as we expect
         # the pypy_method to throw an exception and not to return.  We
         # need them here to satisfy the Java verifier, however, as it
@@ -158,3 +161,10 @@
         if opcode:
             generator.emit(opcode)
 CastPrimitive = _CastPrimitive()
+
+class _PushPyPy(MicroInstruction):
+    """ Pushes the PyPy instance where our helper functions are found
+    from the static field on the generated PyPyMain class """
+    def render(self, generator, op):
+        generator.push_pypy()
+PushPyPy = _PushPyPy()

Modified: pypy/dist/pypy/translator/jvm/methods.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/methods.py	(original)
+++ pypy/dist/pypy/translator/jvm/methods.py	Thu Nov 29 23:20:37 2007
@@ -22,18 +22,16 @@
         self.jrettype = jvmtype.jString
 
     def _print_field_value(self, fieldnm, FIELDOOTY):
-        self.gen.emit(jvmgen.DUP)
         self.gen.load_this_ptr()
         fieldobj = self.clsobj.lookup_field(fieldnm)
         fieldobj.load(self.gen)
         dumpmethod = self.db.toString_method_for_ootype(FIELDOOTY)
         self.gen.emit(dumpmethod)
-        self.gen.emit(jvmgen.PYPYAPPEND)
+        self.gen.emit(jvmgen.STRINGBUILDERAPPEND)
 
     def _print(self, str):
-        self.gen.emit(jvmgen.DUP)
         self.gen.load_string(str)
-        self.gen.emit(jvmgen.PYPYAPPEND)
+        self.gen.emit(jvmgen.STRINGBUILDERAPPEND)
 
     def render(self, gen):
         self.gen = gen

Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py	(original)
+++ pypy/dist/pypy/translator/jvm/node.py	Thu Nov 29 23:20:37 2007
@@ -20,9 +20,9 @@
 from pypy.rpython.ootypesystem import \
      ootype, rclass
 from pypy.translator.jvm.typesystem import \
-     JvmClassType, jString, jStringArray, jVoid, jThrowable, jInt, jPyPyMain, \
+     JvmClassType, jString, jStringArray, jVoid, jThrowable, jInt, \
      jObject, JvmType, jStringBuilder, jPyPyInterlink, jCallbackInterfaces, \
-     JvmInterfaceType
+     JvmInterfaceType, jPyPy
 from pypy.translator.jvm.opcodes import \
      opcodes
 from pypy.translator.jvm.option import \
@@ -91,21 +91,35 @@
         }
 
     def render(self, gen):
-        gen.begin_class(jPyPyMain, jObject)
-        gen.begin_function(
-            'main', (), [jStringArray], jVoid, static=True)
+        gen.begin_class(gen.db.jPyPyMain, jObject)
+        gen.add_field(gen.db.pypy_field)
 
         # Initialization:
         # 
-        #    1. Setup the PyPy helper, which (for now) is a static
-        #    variable of the PyPy class, though that precludes running
-        #    multiple translations.
+        #    1. Create a PyPy helper class, passing in an appropriate
+        #    interlink instance.
         #
         #    2. Run the initialization method for the constant class.
         #
-        gen.new_with_jtype(gen.db.interlink_class)
-        jvmgen.PYPYINTERLINK.store(gen)
+        gen.begin_function(
+            '<clinit>', (), [], jVoid, static=True)
+        gen.emit(jvmgen.NEW, jPyPy)
+        gen.emit(jvmgen.DUP)
+        gen.new_with_jtype(gen.db.jInterlinkImplementation)
+        gen.emit(jvmgen.Method.c(jPyPy, [jPyPyInterlink]))
+        gen.db.pypy_field.store(gen)
         gen.db.constant_generator.runtime_init(gen)
+        gen.return_val(jVoid)
+        gen.end_function()
+        
+        # Main method:
+        # 
+        #    1. Parse the arguments and create Python objects.
+        #    2. Invoke the main function.
+        #    3. Print the result to stdout if self.print_result is true
+        #
+        gen.begin_function(
+            'main', (), [jStringArray], jVoid, static=True)
 
         if self.print_result:
             gen.begin_try()
@@ -116,10 +130,11 @@
             # invoking an appropriate helper function on each one
             for i, arg in enumerate(self.graph.getargs()):
                 jty = self.db.lltype_to_cts(arg.concretetype)
+                conv = self._type_conversion_methods[arg.concretetype]
+                if conv: gen.push_pypy()
                 gen.load_jvm_var(jStringArray, 0)
                 gen.emit(jvmgen.ICONST, i)
                 gen.load_from_array(jString)
-                conv = self._type_conversion_methods[arg.concretetype]
                 if conv: gen.emit(conv)
         else:
             # Convert the array of strings to a List<String> as the

Modified: pypy/dist/pypy/translator/jvm/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/opcodes.py	(original)
+++ pypy/dist/pypy/translator/jvm/opcodes.py	Thu Nov 29 23:20:37 2007
@@ -11,21 +11,40 @@
      CastTo, PushPrimitive
 from pypy.translator.jvm.metavm import \
      IndirectCall, JvmCallMethod, TranslateException, NewCustomDict, \
-     CastPrimitive
+     CastPrimitive, PushPyPy
 from pypy.rpython.ootypesystem import ootype
 
 import pypy.translator.jvm.generator as jvmgen
 import pypy.translator.jvm.typesystem as jvmtype
 
 def _proc(val):
+    if isinstance(val, list):
+        # Lists of instructions we leave alone:
+        return InstructionList(val)
+    elif isinstance(val, jvmgen.Method) and not val.is_static():
+        # For virtual methods, we first push an instance of the relevant
+        # class, then the arguments, and then invoke the method.  Note
+        # that we only allow virtual methods of certain pre-designated
+        # classes to be in the table.
+        if val.class_name == jvmtype.jPyPy.name:
+            return InstructionList(
+                (PushPyPy, PushAllArgs, val, StoreResult))
+        else:
+            raise Exception("Unknown class for non-static method")
+    # For anything else (static methods, strings, etc) we first push
+    # all arguments, then invoke the emit() routine, and finally
+    # store the result.
+    return InstructionList((PushAllArgs, val, StoreResult))
+        
+def _proc_dict(original):
+    
     """ Function which is used to post-process each entry in the
-    opcodes table; it adds a PushAllArgs and StoreResult by default,
-    unless the entry is a list already. """
-    if not isinstance(val, list):
-        val = InstructionList((PushAllArgs, val, StoreResult))
-    else:
-        val = InstructionList(val)
-    return val
+    opcodes table."""
+
+    res = {}
+    for key, val in original.items():
+        res[key] = _proc(val)
+    return res
 
 def _check_zer(op):
     return [TranslateException(
@@ -41,7 +60,7 @@
 
 # This table maps the opcodes to micro-ops for processing them.
 # It is post-processed by _proc.
-_opcodes = {
+opcodes = _proc_dict({
     # __________ object oriented operations __________
     'new':                      [New, StoreResult],
     'runtimenew':               [RuntimeNew, StoreResult],
@@ -58,16 +77,13 @@
     'oohash':                   [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], 
     'oostring':                 [OOString, StoreResult],
     'oounicode':                [OOUnicode, StoreResult],
-    #'ooparse_int':              [PushAllArgs, 'call int32 [pypylib]pypy.runtime.Utils::OOParseInt(string, int32)'],
     'ooparse_float':            jvmgen.PYPYOOPARSEFLOAT,
     'oonewcustomdict':          [NewCustomDict, StoreResult],
-    #
     'same_as':                  DoNothing,
     'hint':                     [PushArg(0), StoreResult],
     'direct_call':              [Call, StoreResult],
     'indirect_call':            [PushAllArgs, IndirectCall, StoreResult],
 
-    #'cast_ptr_to_weakadr':      CastPtrToWeakAddress
     'gc__collect':              jvmgen.SYSTEMGC,
     'gc_set_max_heap_size':     Ignore,
     'resume_point':             Ignore,
@@ -222,7 +238,7 @@
     'ullong_ge':                'ulong_greater_equals',
     'ullong_lshift':            [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult],
     'ullong_rshift':            [PushAllArgs, jvmgen.L2I, jvmgen.LUSHR, StoreResult],
-    'ullong_mod_zer':           _check_zer(jvmgen.PYPYULONGMOD),
+    'ullong_mod_zer':           jvmgen.PYPYULONGMOD,
 
     # when casting from bool we want that every truth value is casted
     # to 1: we can't simply DoNothing, because the CLI stack could
@@ -248,10 +264,4 @@
     'cast_primitive':           [PushAllArgs, CastPrimitive, StoreResult],
     'is_early_constant':        [PushPrimitive(ootype.Bool, False), StoreResult]
     
-}
-
-opcodes = {}
-for opc, val in _opcodes.items():
-    opcodes[opc] = _proc(val)
-del _opcodes
-
+})

Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java	Thu Nov 29 23:20:37 2007
@@ -9,21 +9,33 @@
 import java.text.DecimalFormat;
 
 /**
- * Class with a number of utility routines.
+ * Class with a number of utility routines.  One instance of this is
+ * created by the PyPy entrypoint, and paired with an appropriate
+ * interlink implementation.
  * 
  * I apologize for the Python-esque naming conventions, but it seems
  * I can't switch my mind to camelCase when working so closely with 
  * Python mere minutes before.
+ *
+ * In general, its methods should be virtual.  In some cases, however,
+ * they are static because it is more expedient in the generated code
+ * to not have to push the pypy instance before invoking the method.
  */
 public class PyPy implements Constants {
     
-    public static Interlink interlink;
+    public final Interlink interlink;
+    public final ll_os os;
 
-    public static final long LONG_MAX = Long.MAX_VALUE;
-    public static final long LONG_MIN = Long.MIN_VALUE;
-    public static final int INT_MAX = Integer.MAX_VALUE;
-    public static final int INT_MIN = Integer.MIN_VALUE;
-    public static final double ULONG_MAX = 18446744073709551616.0;
+    public PyPy(Interlink interlink) {
+        this.interlink = interlink;
+        this.os = new ll_os(interlink);
+    }
+
+    public final static long LONG_MAX = Long.MAX_VALUE;
+    public final static long LONG_MIN = Long.MIN_VALUE;
+    public final static int INT_MAX = Integer.MAX_VALUE;
+    public final static int INT_MIN = Integer.MIN_VALUE;
+    public final static double ULONG_MAX = 18446744073709551616.0;
 
     /** 
      * Compares two unsigned integers (value1 and value2) and returns
@@ -68,36 +80,41 @@
         return VALUE2BIGGER;
     }
 
-    public static int uint_mod(int x, int y) {
+    public int uint_mod(int x, int y) {
         long lx = uint_to_long(x);
         long ly = uint_to_long(y);
         long lr = lx % ly;
         return long_to_uint(lr);
     }
 
-    public static int uint_mul(int x, int y)
+    public int uint_mul(int x, int y)
     {
         long xx = uint_to_long(x);
         long yy = uint_to_long(y);
         return long_to_uint(xx * yy);
     }
 
-    public static int uint_div(int x, int y)
+    public int uint_div(int x, int y)
     {
         long xx = uint_to_long(x);
         long yy = uint_to_long(y);
         return long_to_uint(xx / yy);
     }
     
-    public static long ulong_shl(long x, long y) {
+    public long ulong_shl(long x, long y) {
         int yi = (int)y;
         return x << yi;
     }
 
-    public static long ulong_mod(long x, long y) {
+    public long ulong_mod(long x, long y) {
         double dx = ulong_to_double(x);
-        double modulo = Math.IEEEremainder(dx, y);
-        return (long)modulo;
+        try {
+            double modulo = Math.IEEEremainder(dx, y);
+            return (long)modulo;
+        } catch (ArithmeticException e) {
+            interlink.throwZeroDivisionError();
+            return 0; // never reached
+        }
     }
 
     public static int ulong_cmp(long value1, long value2) {
@@ -131,7 +148,7 @@
         return VALUE2BIGGER;
     }
 
-    public static final double BITS16 = (double)0xFFFF;
+    public final double BITS16 = (double)0xFFFF;
 
     public static double uint_to_double(int value) {
         return (double)uint_to_long(value);
@@ -167,7 +184,7 @@
         return res;
     }
 
-    public static long double_to_long(double value)
+    public long double_to_long(double value)
     {
         //if (value <= LONG_MAX)
         //{
@@ -176,11 +193,11 @@
         //TODO: Add some logic here, but I don't think we'll need it
     }
 
-    public static long long_bitwise_negate(long value) {
+    public long long_bitwise_negate(long value) {
         return ~value;
     }
 
-    public static int str_to_int(String s) {
+    public int str_to_int(String s) {
         try {
             return Integer.parseInt(s);
         } catch (NumberFormatException fe) {
@@ -188,7 +205,7 @@
         }
     }
 
-    public static int str_to_uint(String s) {
+    public int str_to_uint(String s) {
         try {
             long l = Long.parseLong(s);
             if (l < Integer.MAX_VALUE)
@@ -201,7 +218,7 @@
         }
     }
 
-    public static long str_to_long(String s) {
+    public long str_to_long(String s) {
         try {
             return Long.parseLong(s);
         } catch (NumberFormatException fe) {
@@ -209,7 +226,7 @@
         }
     }
 
-    public static long str_to_ulong(String s) {
+    public long str_to_ulong(String s) {
         long res = 0;
         s = s.trim();
         for(int i=0; i<s.length(); i++) {
@@ -221,7 +238,7 @@
         return res;
     }
 
-    public static boolean str_to_bool(String s) {
+    public boolean str_to_bool(String s) {
         // not sure what are considered valid boolean values...
         // let's be very accepting and take both strings and numbers
         if (s.equalsIgnoreCase("true"))
@@ -237,7 +254,7 @@
         }
     }
 
-    public static double str_to_double(String s) {
+    public double str_to_double(String s) {
         try {
             return Double.parseDouble(s);
         } catch (NumberFormatException ex) {
@@ -245,22 +262,22 @@
         }
     }
 
-    public static double ooparse_float(String s) {
+    public double ooparse_float(String s) {
         try {
             return Double.parseDouble(s);
         } catch(NumberFormatException ex) {
-            throwValueError();
+            interlink.throwValueError();
             return 0.0; // not reached
         }
     }
 
-    public static char str_to_char(String s) {
+    public char str_to_char(String s) {
         if (s.length() != 1)
             throw new RuntimeException("String not single character: '"+s+"'");
         return s.charAt(0);
     }
 
-    public static double bool_to_double(boolean b) { //This should be replaced with JASMIN code later
+    public double bool_to_double(boolean b) { //This should be replaced with JASMIN code later
         double result;
         if (b)
             result = 1.0;
@@ -274,6 +291,9 @@
     //    A series of methods which serve a similar purpose to repr() in Python:
     //    they create strings that can be exec'd() to rebuild data structures.
     //    Also methods for writing to System.out.
+    //
+    //    These are static because they never throw exceptions etc, and it
+    //    is more convenient that way.
 
     public static void dump(String text) {
         System.out.println(text);
@@ -386,58 +406,58 @@
 
     // ----------------------------------------------------------------------
     // Checked Arithmetic - Overflow protection
-    public static int negate_ovf(int x) 
+    public int negate_ovf(int x) 
     {
         if (x == INT_MIN)
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return -x;
     }
 
-    public static long negate_ovf(long x) 
+    public long negate_ovf(long x) 
     {
         if (x == LONG_MIN)
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return -x;
     }
     
-    public static int abs_ovf(int x) 
+    public int abs_ovf(int x) 
     {
         if (x == INT_MIN)
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return Math.abs(x);
     }
 
-    public static long abs_ovf(long x) 
+    public long abs_ovf(long x) 
     {
         if (x == LONG_MIN)
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return Math.abs(x);
     }
 
-    public static int add_ovf(int x, int y) 
+    public int add_ovf(int x, int y) 
     {
         int result = x+y;
         if (!(((result^x) >=0) || ((result^y) >=0)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
 
-    public static int subtract_ovf(int x, int y) 
+    public int subtract_ovf(int x, int y) 
     {
         int result = x-y;
         if (!(((result^x) >=0) || ((result^(~y)) >=0)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
@@ -458,31 +478,31 @@
         else
             return false;
     }
-    public static int multiply_ovf(int x, int y) 
+    public int multiply_ovf(int x, int y) 
     {
         if (!(int_multiply(x, y)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x * y;
     }
 
-    public static long add_ovf(long x, long y) 
+    public long add_ovf(long x, long y) 
     {
         long result = x+y;
         if (!(((result^x) >=0) || ((result^y) >=0)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
 
-    public static long subtract_ovf(long x, long y) 
+    public long subtract_ovf(long x, long y) 
     {
         long result = x-y;
         if (!(((result^x) >=0) || ((result^(~y)) >=0)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
@@ -503,54 +523,51 @@
         else
             return false;
     }
-    public static long multiply_ovf(long x, long y) 
+    public long multiply_ovf(long x, long y) 
     {
         //if (long_multiply(x, y))
         //{
         //    return x * y;
         //}
         //else
-        //    throwOverflowError();
+        //    interlink.throwOverflowError();
         if (!(long_multiply(x, y)))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x*y;
         //else
-        //    throwOverflowError();
+        //    interlink.throwOverflowError();
     }
 
 
     /* floor division */
-    public static int floordiv_ovf(int x, int y) 
+    public int floordiv_ovf(int x, int y) 
     {
         if ((y == -1) && (x == INT_MIN))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x/y;
     }
 
-    public static int floordiv_zer_ovf(int x, int y) 
+    public int floordiv_zer_ovf(int x, int y) 
     {
-        if (y != 0)
-        {
-            return floordiv_ovf(x,y);
-        }
-        else
-            throw new ArithmeticException("Floor Division with integer by 0");
+        if (y == 0)
+            interlink.throwZeroDivisionError();
+        return floordiv_ovf(x,y);
     }
 
-    public static long floordiv_ovf(long x, long y) 
+    public long floordiv_ovf(long x, long y) 
     {
         if ((y == -1) && (x == LONG_MIN))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x/y;
     }
 
-    public static long floordiv_zer_ovf(long x, long y)
+    public long floordiv_zer_ovf(long x, long y)
     {
         if (y != 0)
         {
@@ -561,41 +578,41 @@
     }
 
     /* modulo */
-    public static int mod_ovf(int x, int y) 
+    public int mod_ovf(int x, int y) 
     {
         if ((y == -1) && (x == INT_MIN))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x%y;
     }
 
-    public static long mod_ovf(long x, long y) 
+    public long mod_ovf(long x, long y) 
     {
         if ((y == -1) && (x == LONG_MIN))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return x%y;
     }
 
     /* shifting */
-    public static int lshift_ovf(int x, int y) // x << y
+    public int lshift_ovf(int x, int y) // x << y
     {
         int result = x << y;
         if (x != (result >> y))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
 
-    public static long lshift_ovf(long x, long y) // x << y
+    public long lshift_ovf(long x, long y) // x << y
     {
         long result = x << y;
         if (x != (result >> y))
         {
-            throwOverflowError();
+            interlink.throwOverflowError();
         }
         return result;
     }
@@ -612,30 +629,29 @@
         return str.indexOf((int) char1) != -1;
     }
 
-    public static int ll_find(String haystack, String needle, int start, int end) {
-        // if it is impossible for the needle to occur:
-        //   this deals w/ a disparity in how java and python handle when needle=""
+    public static int ll_find(String haystack, String needle, 
+                              int start, int end) {
+        // if it is impossible for the needle to occur: this deals w/
+        //   a disparity in how java and python handle when needle=""
         if (start > haystack.length())
             return -1;
 
         int res = haystack.indexOf(needle, start);
-        //System.err.println("haystack="+haystack+" needle="+needle+" start="+start+
-        //                   " end="+end+" res="+res);
         if (res + needle.length() > end) 
             return -1;
         return res;
     }
 
-    public static int ll_rfind(String haystack, String needle, int start, int end) {
+    public static int ll_rfind(String haystack, String needle, 
+                               int start, int end) {
         int res = haystack.lastIndexOf(needle, end-1);
-        //System.err.println("haystack="+haystack+" needle="+needle+" start="+start+
-        //                   " end="+end+" res="+res);
         if (res >= start) 
             return res;
         return -1;
     }
 
-    public static int ll_count(String haystack, String needle, int start, int end) {
+    public static int ll_count(String haystack, String needle, 
+                               int start, int end) {
         haystack = haystack.substring(start, end);
 
         if (needle.length() == 0) {
@@ -651,7 +667,8 @@
         return cnt;
     }
 
-    public static int ll_find_char(String haystack, char needle, int start, int end) {
+    public static int ll_find_char(String haystack, char needle, 
+                                   int start, int end) {
         // see ll_find
         if (start > haystack.length())
             return -1;
@@ -662,16 +679,16 @@
         return res;
     }
 
-    public static int ll_rfind_char(String haystack, char needle, int start, int end) {
+    public static int ll_rfind_char(String haystack, char needle, 
+                                    int start, int end) {
         int res = haystack.lastIndexOf(needle, end-1);
-        //System.err.println("haystack="+haystack+" needle="+needle+" start="+start+
-        //                   " end="+end+" res="+res);
         if (res >= start) 
             return res;
         return -1;
     }
 
-    public static int ll_count_char(String haystack, char needle, int start, int end) {
+    public static int ll_count_char(String haystack, char needle, 
+                                    int start, int end) {
         haystack = haystack.substring(start, end);
         int cnt = 0;
         int idx = -1;
@@ -681,7 +698,8 @@
         return cnt;
     }
 
-    public static String ll_strip(String str, char ch, boolean left, boolean right) {
+    public static String ll_strip(String str, char ch, 
+                                  boolean left, boolean right) {
         int start = 0;
         int end = str.length();
 
@@ -769,11 +787,6 @@
         return s.getBytes();
     }
 
-    public static void append(StringBuilder sb, String s) {
-        // avoid the annoying return value of StringBuilder.append
-        sb.append(s);
-    }
-
     public static ArrayList array_to_list(Object[] array)
     {
         ArrayList list = new ArrayList(java.util.Arrays.asList(array));
@@ -784,7 +797,7 @@
     // ----------------------------------------------------------------------
     // OOString support
     
-    public static String oostring(int n, int base_) {
+    public String oostring(int n, int base_) {
         // XXX needs special case for unsigned ints
         if (base_ == -1)
             base_ = 10;
@@ -794,11 +807,11 @@
             return Integer.toString(n, base_);
     }
 
-    public static String oostring(double d, int base_) {
+    public String oostring(double d, int base_) {
         return new Double(d).toString();
     }
 
-    public static String oostring(Object obj, int base_)
+    public String oostring(Object obj, int base_)
     {
         String clnm = obj.getClass().getName();
         int underscore = clnm.lastIndexOf('_');
@@ -807,22 +820,22 @@
         return String.format("<%s object>", new Object[] { clnm });
     }
 
-    public static String oostring(char ch, int base_)
+    public String oostring(char ch, int base_)
     {
         return new Character(ch).toString();
     }
 
-    public static byte[] oostring(byte[] s, int base_)
+    public byte[] oostring(byte[] s, int base_)
     {
         return s;
     }
 
-    public static String oostring(String s, int base_)
+    public String oostring(String s, int base_)
     {
         return s;
     }
 
-    public static String oostring(boolean b, int base_)
+    public String oostring(boolean b, int base_)
     {
         if (b) return "True";
         return "False";
@@ -831,17 +844,17 @@
     // ----------------------------------------------------------------------
     // OOUnicode support
 
-    public static String oounicode(char ch)
+    public String oounicode(char ch)
     {
         return new Character(ch).toString();
     }
 
-    public static String oounicode(String s)
+    public String oounicode(String s)
     {
         for(int i=0; i<s.length(); i++) {
             char ch = s.charAt(i);
             if ((int)ch > 127)
-                throwUnicodeDecodeError();
+                interlink.throwUnicodeDecodeError();
         }
         return s;
     }
@@ -849,15 +862,15 @@
     // ----------------------------------------------------------------------
     // Primitive built-in functions
 
-    public static double ll_time_clock() {
+    public double ll_time_clock() {
         return System.currentTimeMillis()/1000.0; // XXX: processor time?
     }
 
-    public static double ll_time_time() {
+    public double ll_time_time() {
         return System.currentTimeMillis()/1000.0;
     }
     
-    public static void ll_time_sleep(double seconds)
+    public void ll_time_sleep(double seconds)
     {
         double startTime = ll_time_time();
         double endTime = startTime + seconds;
@@ -870,12 +883,12 @@
         } while (startTime < endTime);
     }
     
-    public static String ll_join(String a, String b)
+    public String ll_join(String a, String b)
     {
         return a + "/" + b; // XXX
     }
 
-    public static String ll_strtod_formatd(String format, double d)
+    public String ll_strtod_formatd(String format, double d)
     {
         // XXX: this is really a quick hack to make things work.
         // it should disappear, because this function is not
@@ -884,27 +897,6 @@
     }
 
     // ----------------------------------------------------------------------
-    // Exceptions
-    //
-    // If we don't use true Java exceptions, then this 
-
-/*
-    static private ThreadLocal<Object> excObject  = new ThreadLocal();
-
-    public static int startTry() {
-        return excCounter.get();
-    }
-
-    public void throw(Object o) {
-        excObject.put(o);
-    }
-
-    public static Object catch(int ctr) {
-        return excObject.get();
-    }
-*/
-
-    // ----------------------------------------------------------------------
     // Dicts
     //
     // Note: it's easier to cut and paste a few methods here than
@@ -966,56 +958,29 @@
     // ----------------------------------------------------------------------
     // ll_math
 
-    public static double ll_math_floor(double x)
+    public double ll_math_floor(double x)
     {
         return Math.floor(x);
     }
 
-    public static double ll_math_fmod(double x, double y)
+    public double ll_math_fmod(double x, double y)
     {
         return x % y;
     }
 
-    public static double ll_math_ldexp(double v, int w) {
+    public double ll_math_ldexp(double v, int w) {
         return check(v * Math.pow(2.0, w));
     }
 
-    private static double check(double v) {
+    private double check(double v) {
         if (Double.isNaN(v))
-            throwValueError();
+            interlink.throwValueError();
         if (Double.isInfinite(v))
-            throwOverflowError();
+            interlink.throwOverflowError();
         return v;
     }
 
     // ----------------------------------------------------------------------
-    // Convenient Helpers for throwing exceptions
-    //
-    // Also, an abstraction barrier: at a later date we may want to
-    // switch to using thread-local data rather than a global variable,
-    // and if so we can easily do it in these functions here.
-
-    public static void throwZeroDivisionError() {
-        interlink.throwZeroDivisionError();
-    }
-
-    public static void throwIndexError() {
-        interlink.throwIndexError();
-    }
-
-    public static void throwOverflowError() {
-        interlink.throwOverflowError();
-    }
-
-    public static void throwValueError() {
-        interlink.throwValueError();
-    }
-
-    public static void throwUnicodeDecodeError() {
-        interlink.throwUnicodeDecodeError();
-    }
-    
-    // ----------------------------------------------------------------------
     // Self Test
 
     public static int __counter = 0, __failures = 0;
@@ -1033,6 +998,8 @@
     public static void main(String args[]) {
         // Small self test:
 
+        PyPy pypy = new PyPy(null);
+
         ensure(uint_cmp(0xFFFFFFFF, 0) > 0);
         ensure(uint_cmp(0, 0xFFFFFFFF) < 0);
         ensure(uint_cmp(0x80000000, 0) > 0);

Modified: pypy/dist/pypy/translator/jvm/src/pypy/ll_os.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/pypy/ll_os.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/pypy/ll_os.java	Thu Nov 29 23:20:37 2007
@@ -18,11 +18,13 @@
 
 class PrintStreamWrapper extends FileWrapper
 {
-    private PrintStream stream;
+    private final PrintStream stream;
+    private final ll_os os;
 
-    public PrintStreamWrapper(PrintStream stream)
+    public PrintStreamWrapper(PrintStream stream, ll_os os)
     {
         this.stream = stream;
+        this.os = os;
     }
 
     public void write(String buffer)
@@ -32,13 +34,13 @@
 
     public String read(int count)
     {
-        ll_os.throwOSError(PyPy.EBADF, "Write-only fd");
+        os.throwOSError(PyPy.EBADF, "Write-only fd");
         return null; // never reached
     }
 
     public void close()
     {
-        ll_os.throwOSError(PyPy.EBADF, "Cannot close stdout or stderr");
+        os.throwOSError(PyPy.EBADF, "Cannot close stdout or stderr");
     }
 
     public RandomAccessFile getFile()
@@ -49,16 +51,18 @@
 
 class InputStreamWrapper extends FileWrapper
 {
-    private InputStream stream;
+    private final InputStream stream;
+    private final ll_os os;
 
-    public InputStreamWrapper(InputStream stream)
+    public InputStreamWrapper(InputStream stream, ll_os os)
     {
         this.stream = stream;
+        this.os = os;
     }
 
     public void write(String buffer)
     {
-        ll_os.throwOSError(PyPy.EBADF, "Read-only fd");
+        os.throwOSError(PyPy.EBADF, "Read-only fd");
     }
 
     public String read(int count)
@@ -71,14 +75,14 @@
             return new String(buf, 0, n);
         }
         catch(IOException e) {
-            ll_os.throwOSError(PyPy.EIO, e.getMessage());
+            os.throwOSError(PyPy.EIO, e.getMessage());
             return null; // never reached
         }
     }
 
     public void close()
     {
-        ll_os.throwOSError(PyPy.EBADF, "Cannot close stdin");
+        os.throwOSError(PyPy.EBADF, "Cannot close stdin");
     }
 
     public RandomAccessFile getFile()
@@ -89,34 +93,39 @@
 
 class RandomAccessFileWrapper extends FileWrapper
 {
-    private RandomAccessFile file;
-    private boolean canRead;
-    private boolean canWrite;
-
-    public RandomAccessFileWrapper(RandomAccessFile file, boolean canRead, boolean canWrite)
+    private final RandomAccessFile file;
+    private final boolean canRead;
+    private final boolean canWrite;
+    private final ll_os os;
+
+    public RandomAccessFileWrapper(RandomAccessFile file, 
+                                   boolean canRead, 
+                                   boolean canWrite,
+                                   ll_os os)
     {
         this.file = file;
         this.canRead = canRead;
         this.canWrite = canWrite;
+        this.os = os;
     }
 
     public void write(String buffer)
     {
         if (!this.canWrite)
-            ll_os.throwOSError(PyPy.EBADF, "Cannot write to this fd");
+            os.throwOSError(PyPy.EBADF, "Cannot write to this fd");
 
         try {
             this.file.writeBytes(buffer);
         }
         catch(IOException e) {
-            ll_os.throwOSError(PyPy.EIO, e.getMessage());
+            os.throwOSError(PyPy.EIO, e.getMessage());
         }
     }
 
     public String read(int count)
     {
         if (!this.canRead)
-            ll_os.throwOSError(PyPy.EBADF, "Cannot read from this fd");
+            os.throwOSError(PyPy.EBADF, "Cannot read from this fd");
 
         try {
             byte[] buffer = new byte[count];
@@ -127,7 +136,7 @@
                 return new String(buffer, 0, n);
         }
         catch(IOException e) {
-            ll_os.throwOSError(PyPy.EIO, e.getMessage());
+            os.throwOSError(PyPy.EIO, e.getMessage());
             return null; // never reached
         }
     }
@@ -138,7 +147,7 @@
             this.file.close();
         }
         catch(IOException e) {
-            ll_os.throwOSError(PyPy.EIO, e.getMessage());
+            os.throwOSError(PyPy.EIO, e.getMessage());
         }
     }
 
@@ -172,36 +181,40 @@
     private static final int SEEK_CUR = 1;
     private static final int SEEK_END = 2;
 
-    private static int fdcount;
-    private static Map<Integer, FileWrapper> FileDescriptors = new HashMap<Integer, FileWrapper>();
-    private static Map<Integer, String> ErrorMessages = new HashMap<Integer, String>();
-
-    static {
-        FileDescriptors.put(new Integer(0), new InputStreamWrapper(System.in));
-        FileDescriptors.put(new Integer(1), new PrintStreamWrapper(System.out));
-        FileDescriptors.put(new Integer(2), new PrintStreamWrapper(System.err));
+    private int fdcount;
+    private final Map<Integer, FileWrapper> FileDescriptors = 
+      new HashMap<Integer, FileWrapper>();
+    private final Map<Integer, String> ErrorMessages = 
+      new HashMap<Integer, String>();
+    private final Interlink interlink;
+
+    public ll_os(Interlink interlink) {
+        this.interlink = interlink;
+        FileDescriptors.put(0, new InputStreamWrapper(System.in, this));
+        FileDescriptors.put(1, new PrintStreamWrapper(System.out, this));
+        FileDescriptors.put(2, new PrintStreamWrapper(System.err, this));
         fdcount = 2;
     }
-    
+
     public static final boolean STRACE = false;
     public static void strace(String arg) {
         System.err.println(arg);
     }
 
-    public static void throwOSError(int errno, String errText) {
-        ErrorMessages.put(new Integer(errno), errText);
-        PyPy.interlink.throwOSError(errno);
+    public void throwOSError(int errno, String errText) {
+        ErrorMessages.put(errno, errText);
+        interlink.throwOSError(errno);
     }
 
-    private static FileWrapper getfd(int fd)
+    private FileWrapper getfd(int fd)
     {
-        FileWrapper f = FileDescriptors.get(new Integer(fd));
+        FileWrapper f = FileDescriptors.get(fd);
         if (f == null)
             throwOSError(PyPy.EBADF, "Invalid file descriptor: " + fd);
         return f;
     }
 
-    private static RandomAccessFile open_file(String name, String javaMode, int flags)
+    private RandomAccessFile open_file(String name, String javaMode, int flags)
     {
         RandomAccessFile file;
 
@@ -228,7 +241,7 @@
         return file;
     }
 
-    public static int ll_os_open(String name, int flags, int mode)
+    public int ll_os_open(String name, int flags, int mode)
     {
         boolean canRead = false;
         boolean canWrite = false;
@@ -246,24 +259,25 @@
 
         // XXX: we ignore O_CREAT
         RandomAccessFile file = open_file(name, javaMode, flags);
-        RandomAccessFileWrapper wrapper = new RandomAccessFileWrapper(file, canRead, canWrite);
+        RandomAccessFileWrapper wrapper = 
+          new RandomAccessFileWrapper(file, canRead, canWrite, this);
 
         fdcount++;
-        FileDescriptors.put(new Integer(fdcount), wrapper);
+        FileDescriptors.put(fdcount, wrapper);
 
         if (STRACE) strace("ll_os_open: "+name+"->"+fdcount);
         return fdcount;
     }
 
-    public static void ll_os_close(int fd)
+    public void ll_os_close(int fd)
     {
         if (STRACE) strace("ll_os_close: "+fd);
         FileWrapper wrapper = getfd(fd);
         wrapper.close();
-        FileDescriptors.remove(new Integer(fd));
+        FileDescriptors.remove(fd);
     }
 
-    public static int ll_os_dup(int fd)
+    public int ll_os_dup(int fd)
     {
         FileWrapper wrapper = getfd(fd);
         for (int i = 0; i < Integer.MAX_VALUE; i++) {
@@ -277,19 +291,19 @@
         return -1;
     }
     
-    public static String ll_os_read(int fd, int count)
+    public String ll_os_read(int fd, int count)
     {
         if (STRACE) strace("ll_os_read: "+fd);
         return getfd(fd).read(count);
     }
 
-    public static String ll_os_read(int fd, long count)
+    public String ll_os_read(int fd, long count)
     {
         if (STRACE) strace("ll_os_read: "+fd);
         return ll_os_read(fd, (int)count);
     }
 
-    public static long ll_os_lseek(int fd, long offset, int whence)
+    public long ll_os_lseek(int fd, long offset, int whence)
     {
         if (STRACE) strace("ll_os_lseek: "+fd);
         FileWrapper wrapper = getfd(fd);
@@ -320,30 +334,30 @@
         return pos;
     }
 
-    public static StatResult ll_os_lstat(String path)
+    public StatResult ll_os_lstat(String path)
     {
         return ll_os_stat(path); // XXX
     }
 
-    public static String ll_os_strerror(int errno)
+    public String ll_os_strerror(int errno)
     {
-        String msg = ErrorMessages.remove(new Integer(errno));
+        String msg = ErrorMessages.remove(errno);
         if (msg == null)
             return "errno: " + errno;
         else
             return msg;
     }
 
-    public static int ll_os_write(int fd, String text) {
+    public int ll_os_write(int fd, String text) {
         if (STRACE) strace("ll_os_write: "+fd+" "+text);        
-        FileWrapper f = FileDescriptors.get(new Integer(fd));
+        FileWrapper f = FileDescriptors.get(fd);
         if (f == null)
             throwOSError(PyPy.EBADF, "Invalid fd: " + fd);
         f.write(text);
         return text.length();
     }
 
-    public static boolean ll_os_isatty(int x)
+    public boolean ll_os_isatty(int x)
     {
         // XXX: this is not the right behaviour, but it's needed
         // to have the interactive interpreter working
@@ -353,25 +367,25 @@
             return false;
     }
 
-    public static String ll_os_getenv(String key)
+    public String ll_os_getenv(String key)
     {
         return System.getenv(key);
     }
     
-    public static void ll_os_putenv(String key, String value)
+    public void ll_os_putenv(String key, String value)
     {
         //System.setenv(key, value);
         // it appears that there is no such method??!!
     }    
     
-    public static ArrayList ll_os_envkeys()
+    public ArrayList ll_os_envkeys()
     {
         Map variables = System.getenv();
         Set variableNames = variables.keySet();
         return new ArrayList(variableNames);
     }
     
-    public static ArrayList ll_os_envitems()
+    public ArrayList ll_os_envitems()
     {
         Map variables = System.getenv();
         Set variableNames = variables.keySet();
@@ -382,13 +396,13 @@
         {
              String name = (String) nameIterator.next();
              String value = (String) variables.get(name);
-             result.add(PyPy.interlink.recordStringString(name, value));
+             result.add(interlink.recordStringString(name, value));
         }
         
         return result;
     }
     
-    public static ArrayList<String> ll_os_listdir(String path)
+    public ArrayList<String> ll_os_listdir(String path)
     {
         if (path == "")
             throwOSError(PyPy.ENOENT, "No such file or directory: ''");
@@ -400,15 +414,15 @@
         return new ArrayList(Arrays.asList(f.list()));
     }
 
-    public static String ll_os_getcwd()
+    public String ll_os_getcwd()
     {
         return System.getProperty("user.dir");
     }
 
-    public static StatResult ll_os_stat(String path)
+    public StatResult ll_os_stat(String path)
     {
         if (path.equals(""))
-            ll_os.throwOSError(PyPy.ENOENT, "No such file or directory: ''");
+            throwOSError(PyPy.ENOENT, "No such file or directory: ''");
 
         File f = new File(path);
         
@@ -424,7 +438,7 @@
             return res;
         }
 
-        ll_os.throwOSError(PyPy.ENOENT, "No such file or directory: '"+path+"'");
+        throwOSError(PyPy.ENOENT, "No such file or directory: '"+path+"'");
         return null; // never reached
     }
 }

Modified: pypy/dist/pypy/translator/jvm/typesystem.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/typesystem.py	(original)
+++ pypy/dist/pypy/translator/jvm/typesystem.py	Thu Nov 29 23:20:37 2007
@@ -172,9 +172,8 @@
 jArrayList = JvmClassType('java.util.ArrayList')
 jPyPy = JvmClassType('pypy.PyPy')
 jPyPyExcWrap = JvmClassType('pypy.ExceptionWrapper')
-jPyPyMain = JvmClassType('pypy.Main')
 jPyPyDictItemsIterator = JvmClassType('pypy.DictItemsIterator')
-jPyPyInterlink = JvmClassType('pypy.Interlink')
+jPyPyInterlink = JvmInterfaceType('pypy.Interlink')
 jPyPyCustomDict = JvmClassType('pypy.CustomDict')
 jPyPyStatResult = JvmClassType('pypy.StatResult')
 jPyPyWeakRef = JvmClassType('pypy.PyPyWeakRef')

Modified: pypy/dist/pypy/translator/oosupport/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/metavm.py	(original)
+++ pypy/dist/pypy/translator/oosupport/metavm.py	Thu Nov 29 23:20:37 2007
@@ -172,13 +172,42 @@
         Stack: argN, arg2, arg1, this, ... -> ret, ... """
         raise NotImplementedError
 
+    def prepare_call_primitive(self, op, module, name):
+        """ see call_primitive: by default does nothing """
+        pass
+        
     def call_primitive(self, op, module, name):
         """ Like call_graph, but it has been suggested that the method be
-        rendered as a primitive.
+        rendered as a primitive.  The full sequence for invoking a primitive:
+
+          self.prepare_call_primitive(op, module, name)
+          for each arg: self.load(arg)
+          self.call_primitive(op, module, name)
 
         Stack: argN...arg2, arg1, arg0, ... -> ret, ... """
         raise NotImplementedError
 
+    def prepare_call_oostring(self, OOTYPE):
+        " see call_oostring "
+        pass
+
+    def call_oostring(self, OOTYPE):
+        """ Invoked for the oostring opcode with both operands
+        (object, int base) already pushed onto the stack.
+        prepare_call_oostring() is invoked before the operands are
+        pushed."""
+        raise NotImplementedError
+
+    def prepare_call_oounicode(self, OOTYPE):
+        " see call_oounicode "
+        pass
+
+    def call_oounicode(self, OOTYPE):
+        """ Invoked for the oounicode opcode with the operand already
+        pushed onto the stack.  prepare_call_oounicode() is invoked
+        before the operand is pushed. """
+        raise NotImplementedError
+
     def new(self, TYPE):
         """ Creates a new object of the given type.
 
@@ -415,11 +444,14 @@
         callee = op.args[0].value
         is_primitive = self._get_primitive_name(callee)
 
+        if is_primitive:
+            module, name = is_primitive
+            generator.prepare_call_primitive(op, module, name)
+
         for arg in op.args[1:]:
             generator.load(arg)
-        
+
         if is_primitive:
-            module, name = is_primitive
             generator.call_primitive(op, module, name)
         else:
             generator.call_graph(callee.graph)
@@ -442,6 +474,7 @@
 class _OOString(MicroInstruction):
     def render(self, generator, op):
         ARGTYPE = op.args[0].concretetype
+        generator.prepare_call_oostring(ARGTYPE)
         generator.load(op.args[0])
         generator.load(op.args[1])
         generator.call_oostring(ARGTYPE)
@@ -452,6 +485,7 @@
         assert v_base.value == -1, "The second argument of oounicode must be -1"
 
         ARGTYPE = op.args[0].concretetype
+        generator.prepare_call_oounicode(ARGTYPE)
         generator.load(op.args[0])
         generator.call_oounicode(ARGTYPE)
 

Modified: pypy/dist/pypy/translator/oosupport/test_template/builtin.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/test_template/builtin.py	(original)
+++ pypy/dist/pypy/translator/oosupport/test_template/builtin.py	Thu Nov 29 23:20:37 2007
@@ -32,10 +32,28 @@
         res = self.ll_to_string(self.interpret(fn, [False]))
         assert res == file(tmpfile, 'r').read()
 
+    def test_os_dup_oo(self):
+        tmpdir = str(udir.udir.join("os_dup_oo"))
+        def fn():
+            fd = os.open(tmpdir, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0777)
+            os.write(fd, "hello world")
+            fd2 = os.dup(fd)
+            os.write(fd2, " (dupped)")
+            os.close(fd)
+            try:
+                os.write(fd2, " (uh oh)")
+            except OSError, e:
+                return e.errno
+            return -1
+        assert self.interpret(fn, []) == 5 # EIO
+        assert file(tmpdir).read() == 'hello world (dupped)'
+
     # the following tests can't be executed with gencli because they
     # returns file descriptors, and cli code is executed in another
-    # process. Instead of those, there is a new test that opens and
+    # process. Instead of those, there are new tests that opens and
     # write to a file all in the same process.
+    def test_os_dup(self):
+        pass
     def test_os_write(self):
         pass
     def test_os_write_single_char(self):

Modified: pypy/dist/pypy/translator/oosupport/test_template/constant.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/test_template/constant.py	(original)
+++ pypy/dist/pypy/translator/oosupport/test_template/constant.py	Thu Nov 29 23:20:37 2007
@@ -22,6 +22,14 @@
         assert res.item0 == 1
         assert res.item1 == 2
 
+    def test_tuples_of_different_types(self):
+        const = "1", "2"
+        def fn():
+            return const
+        res = self.interpret(fn, [])
+        assert res.item0 == "1"
+        assert res.item1 == "2"
+
     def test_list(self):
         const = [1, 2]
         def fn():



More information about the Pypy-commit mailing list