Armin Rigo avatar Armin Rigo committed 2b24249

More fix fix. Sanitize runner_test, at least when compared to the
previous situation.

Comments (0)

Files changed (4)

pypy/jit/backend/llgraph/runner.py

         if isinstance(arg, Const):
             return arg.value
         result = self.env[arg]
-        assert result == self.framecontent[arg.getvarindex()]
+        assert result is self.framecontent[arg.getvarindex()]
+        if arg.type == FLOAT and FLOAT_SIZE > 1:
+            assert self.framecontent[arg.getvarindex() + 1] == '2nd float word'
         return result
 
     def execute(self, lltrace):

pypy/jit/backend/test/runner_test.py

                                          JitCellToken, TargetToken)
 from pypy.jit.metainterp.resoperation import rop, create_resop_dispatch,\
      create_resop, ConstInt, ConstPtr, ConstFloat, create_resop_2,\
-     create_resop_1, create_resop_0, INT, REF, FLOAT, example_for_opnum,\
+     create_resop_1, create_resop_0, INT, REF, FLOAT, VOID, example_for_opnum,\
      AbstractResOp
 from pypy.jit.metainterp.test.support import boxint, boxfloat,\
      boxlonglong_on_32bit, boxptr, constfloat
     bridge_loop_instruction = ['overload for a specific cpu']
     _nextvarindex = 0
 
-    def _prepare_valuebox(self, box):
-        if isinstance(box, AbstractResOp):
-            box = box.getforwarded()
-            if getattr(box, '_varindex', 42) < 0:
-                while self._nextvarindex in self._seen_varindex:
-                    self._nextvarindex += 1
-                box.setvarindex(self._nextvarindex)
-                self._nextvarindex += 1
-        return box
+    def update_varindexes(self, newtext2op):
+        # 'self.text2op' is a dict mapping variable names (as present in
+        # the oparser source) to the corresponding ResOp.  This function
+        # updates it with 'newtext2op', then assigns '_varindex' to all
+        # the new ResOps.  The choice of '_varindex' is done automatically
+        # to avoid conflicts, but existing '_varindex' are not changed.
+        # If 'newtext2op' is not a dict but a list, comes up with names
+        # as per str(op).
+        if isinstance(newtext2op, list):
+            newtext2op = dict([(str(op), op) for op in newtext2op])
+        try:
+            text2op = self.text2op
+        except AttributeError:
+            text2op = self.text2op = {}
+        text2op.update(newtext2op)
+        if newtext2op:
+            # update 'self._nextvarindex' to a value higher than any seen
+            # in newtext2op.  Pick two more rather than one more just in
+            # case the highest so far was a FLOAT.
+            newops = newtext2op.values()
+            random.shuffle(newops)
+            maximum = max([getattr(op, '_varindex', -2) for op in newops])
+            self._nextvarindex = max(self._nextvarindex, maximum + 2)
+            for op in newops:
+                self.assign_varindex(op)
 
-    def _fetch_varindex(self, box):
-        return getattr(box, '_varindex', -1)
+    def assign_varindex(self, op):
+        if (isinstance(op, AbstractResOp) and op.type != VOID and
+                getattr(op, '_varindex', -1) == -1):
+            op._varindex = self._nextvarindex
+            if hasattr(op, '_str'):
+                del op._str     # recompute it
+            # this op consumes either one or two numbers, depending on its
+            # type as a non-FLOAT or FLOAT.  We don't care too much about
+            # being on 32-bit vs 64-bit here.
+            self._nextvarindex += 1 + (op.type == FLOAT)
 
     def execute_operation(self, opname, valueboxes, result_type, descr=None):
-        self._seen_varindex = set(map(self._fetch_varindex, valueboxes))
-        valueboxes = map(self._prepare_valuebox, valueboxes)
         inputargs, operations = self._get_single_operation_list(opname,
                                                                 result_type,
                                                                 valueboxes,
                                                                 descr)
+        self.update_varindexes(inputargs + operations)
         looptoken = JitCellToken()
         self.cpu.compile_loop(inputargs, operations, looptoken)
         args = []
         if result is None:
             results = []
         else:
-            op0 = self._prepare_valuebox(op0)
             results = [op0]
         op1 = create_resop(rop.FINISH, None, results, descr=BasicFailDescr(0),
                            mutable=True)
         if 'faildescr4' not in namespace:
             namespace['faildescr4'] = BasicFailDescr(4)
         loop = oparser.parse(s, namespace=namespace, mutable=True,
-                             oldvars=getattr(self, 'original_vars', {}))
-        self.original_vars = loop.original_vars
+                             oldvars=getattr(self, 'text2op', {}))
+        self.update_varindexes(loop.text2op)
         return loop.inputargs, loop.operations, JitCellToken()
 
     def get_frame_value(self, frame, varname):
-        op = self.original_vars[varname]
+        op = self.text2op[varname]
         index = op.getvarindex()
         if varname.startswith('i'):
             return self.cpu.get_frame_value_int(frame, index)
         for nb_args in range(50):
             print 'Passing %d arguments to execute_token...' % nb_args
             #
+            text2op = {}
             inputargs = []
             values = []
             for k in range(nb_args):
                 if kind == 0:
                     inputargs.append(boxint())
                     values.append(r.randrange(-100000, 100000))
+                    text2op['ii%d' % k] = inputargs[-1]
                 else:
                     inputargs.append(boxfloat())
                     values.append(longlong.getfloatstorage(r.random()))
+                    text2op['fi%d' % k] = inputargs[-1]
             #
             looptoken = JitCellToken()
             faildescr = BasicFailDescr(42)
             operations = []
-            retboxes = []
-            retvalues = []
             #
             ks = range(nb_args)
             random.shuffle(ks)
+            retvalues = []
             for k in ks:
                 if inputargs[k].type == INT:
                     x = r.randrange(-100000, 100000)
                         create_resop_2(rop.INT_ADD, 0, inputargs[k],
                                        ConstInt(x))
                         )
+                    text2op['io%d' % k] = operations[-1]
                     y = values[k] + x
                 else:
                     x = r.random()
                         create_resop_2(rop.FLOAT_ADD, 0.0, inputargs[k],
                                        constfloat(x))
                         )
+                    text2op['fo%d' % k] = operations[-1]
                     y = longlong.getrealfloat(values[k]) + x
                     y = longlong.getfloatstorage(y)
-                kk = r.randrange(0, len(retboxes)+1)
-                retboxes.insert(kk, operations[-1])
-                retvalues.insert(kk, y)
+                retvalues.append(y)
             #
             operations.append(
                 create_resop(rop.FINISH, None, [], descr=faildescr,
                              mutable=True)
                 )
-            operations[-1].setfailargs(retboxes)
+            self.update_varindexes(text2op)
             print inputargs
             for op in operations:
                 print op
             frame = self.cpu.execute_token(looptoken, *values)
             assert self.cpu.get_latest_descr(frame).identifier == 42
             #
-            for k in range(len(retvalues)):
-                if retboxes[k].type == 'i':
-                    got = self.cpu.get_latest_value_int(frame, k)
+            for k, expected in zip(ks, retvalues):
+                if 'io%d' % k in text2op:
+                    got = self.get_frame_value(frame, 'io%d' % k)
                 else:
-                    got = self.cpu.get_latest_value_float(frame, k)
-                assert got == retvalues[k]
+                    got = self.get_frame_value(frame, 'fo%d' % k)
+                assert got == expected
 
     def test_jump(self):
         # this test generates small loops where the JUMP passes many

pypy/jit/metainterp/resoperation.py

     @classmethod
     def returns_bool_result(cls):
         opnum = cls.getopnum()
-        if we_are_translated():
-            assert opnum >= 0
+        if opnum < 0:
+            return False
         return opboolresult[opnum]
 
     def _copy_extra_attrs(self, new):
         pass
-    
+
+    def getvarindex(self):
+        # for testing only: even non-mutable ResOperations have a
+        # getvarindex() that works by reading '_varindex'.  This
+        # is convenient for runner_test.py.
+        if we_are_translated():
+            raise NotImplementedError
+        assert self._varindex >= 0    # and hasattr(self, '_varindex')
+        return self._varindex
+
     # some debugging help
 
     def __setattr__(self, attr, val):

pypy/jit/tool/oparser.py

                                          mutable=self.mutable)
                 else:
                     raise ParseError("Unknown variable type: %s" % elem)
-                self.setstr(box, elem)
+                box._str = elem
             else:
                 box = self.oldvars[elem]
             self.vars[elem] = box
         return self.vars[elem]
 
-    def setstr(self, op, text):
-        if hasattr(op, 'setvarindex') and text[1:].isdigit():
-            op.setvarindex(int(text[1:]))
-        else:
-            op._res = text
-
     def is_float(self, arg):
         try:
             float(arg)
         else:
             result = self.results[num]
         opres = self.create_op(opnum, result, args, descr)
-        self.setstr(opres, res)
+        opres._str = res
         self.vars[res] = opres
         return opres
 
         loop.operations = ops
         loop.inputargs = inpargs
         loop.last_offset = last_offset
-        loop.original_vars = self.vars
+        loop.text2op = self.vars
         return loop
 
     def parse_ops(self, indent, lines, start):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.