Antonio Cuni avatar Antonio Cuni committed a111894

try yet another way to encode bytecodes; this time, opargs are decoded
in advance, but they are stored togheter with the opcodes in a list of
ints. This code is not very well tested nor well written, I commit it
just to do benchmarks on different machines

Comments (0)

Files changed (3)

pypy/config/pypyoption.py

                default=False,
                requires=[("objspace.usepycfiles", False)]),
 
+    BoolOption("predecodeargs", "predecode opargs and opcodes, but store them in the same list",
+               default=False,
+               requires=[("objspace.usepycfiles", False)]),
+
     BoolOption("honor__builtins__",
                "Honor the __builtins__ key of a module dictionary",
                default=False),

pypy/interpreter/pycode.py

         return self._signature
 
     def precompute_code(self, code):
-        from pypy.interpreter.pyopcode import decode_opcode
-        if not self.space.config.objspace.usecodeargs:
+        if self.space.config.objspace.usecodeargs:
+            self.compute_codeargs(code)
+        elif self.space.config.objspace.predecodeargs:
+            self.precompute_codeargs(code)
+        else:
+            # "normal" case
             self.co_code = code
             self.co_codeargs = None
-            return
 
+    def compute_codeargs(self, code):
+        from pypy.interpreter.pyopcode import decode_opcode
         next_instr = 0
         codeargs = []
         codelist = []
         self.co_code = ''.join(codelist)
         self.co_codeargs = codeargs
 
+    def precompute_codeargs(self, code):
+        from pypy.interpreter.pyopcode import decode_opcode
+        next_instr = 0
+        codelist = []
+        orig2new = {} # index in code --> index in codelist
+        new2orig = {} # index in codelist --> index in code
+        while next_instr < len(code):
+            opcode = ord(code[next_instr])
+            orig2new[next_instr] = len(codelist)
+            new2orig[len(codelist)] = next_instr
+            next_instr += 1
+            next_instr, opcode, oparg = decode_opcode(code, next_instr, opcode)
+            codelist.append(opcode)
+            codelist.append(oparg)
+
+        # sanity check
+        for i, j in orig2new.iteritems():
+            assert ord(code[i]) == codelist[j]
+
+        # recompute target addresses
+        i = 0
+        while i<len(codelist):
+            opcode = codelist[i]
+            i+=1
+            oparg = codelist[i]
+            if opcode in stdlib_opcode.hasjabs:
+                codelist[i] = orig2new[oparg]
+            elif opcode in stdlib_opcode.hasjrel:
+                orig_from = new2orig[i-1]
+                orig_to = orig_from + oparg + 3
+                new_from = i
+                new_to = orig2new[orig_to]
+                new_offset = new_to - new_from - 1
+                assert (new_offset % 2) == 0
+                codelist[i] = new_offset
+            i+=1
+
+        self.co_code = code
+        self.co_codeargs = codelist
+
     def _from_code(space, code, hidden_applevel=False):
         """ Initialize the code object from a real (CPython) one.
             This is just a hack, until we have our own compile.

pypy/interpreter/pyopcode.py

     def dispatch_bytecode(self, co_code, co_codeargs, next_instr, ec):
         space = self.space
         while True:
-            
+
             self.last_instr = intmask(next_instr)
             if not we_are_jitted():
                 ec.bytecode_trace(self)
                 next_instr = r_uint(self.last_instr)
-            opcode = ord(co_code[next_instr])
+
+            if space.config.objspace.usecodeargs:
+                opcode = ord(co_code[next_instr])
+                oparg = co_codeargs[next_instr]
+                next_instr += 1
+            elif space.config.objspace.predecodeargs:
+                opcode = co_codeargs[next_instr]
+                oparg = co_codeargs[next_instr+1]
+                next_instr += 2
+            else:
+                opcode = ord(co_code[next_instr])
+                next_instr += 1
+                next_instr, opcode, oparg = decode_opcode(co_code, next_instr, opcode)
 
             if space.config.objspace.logbytecodes:
                 space.bytecodecounts[opcode] = space.bytecodecounts.get(opcode, 0) + 1
 
-            if space.config.objspace.usecodeargs:
-                oparg = co_codeargs[next_instr]
-                next_instr += 1
-            else:
-                next_instr += 1
-                next_instr, opcode, oparg = decode_opcode(co_code, next_instr, opcode)
-
             if opcode == opcodedesc.RETURN_VALUE.index:
                 w_returnvalue = self.popvalue()
                 block = self.unrollstack(SReturnValue.kind)
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.